Php search with multiple values - php

i try to make a search system which has multiple inputs. I tried to to select the data in query and that it supose to add the aditional data if it exist but it dont do that. i messed it up and dont know how to fix it. The data from my other file gets there. I checked it. Did anyone know what i did wrong?
<?php
$connect= mysqli_connect("localhost", "root", "root", "website");
$query = "SELECT * FROM data";
$sort = " date DESC"
if(isset($_GET["search"])){
$keywordsearch = $connect->escape_string($_GET['search']);
$query .= " WHERE name like '%$keywordsearch%'";
if(isset($_GET['tag'])){
$keywordtag = $connect->escape_string($_GET['tag']);
$query .= " AND tag like '%$keywordtag%'";
$query .= " ORDER BY $sort";
}
}
$result = mysqli_query($connect, $query);
while($row = mysqli_fetch_array($result)){
echo $row['name']."<br>";
}
?>

This can be done by creating an array of the data passed in and using that array you can control all the other requirements to build a query and pass parameters using a Parameterised and bound query
$_GET = ['search'=> 'fluff', 'tag'=>'easy'];
$connect= mysqli_connect("localhost", "root", "root", "website");
$query = "SELECT * FROM data";
$sort = " ORDER BY date DESC";
if(isset($_GET["search"])){
$query .= " WHERE name like ?";
$vals[] = '%' . $_GET["search"] . '%';
}
if(isset($_GET['tag'])){
$query .= " OR tag like ?";
$vals[] = '%' . $_GET["tag"] . '%';
}
$query .= $sort;
$types = str_repeat('s', count($vals));
$stmt = $connect->prepare($query);
$stmt->bind_param($types, ...$vals);
$stmt->execute();
$result = $stmt->get_result();
while($row = $result->fetch_array(MYSQLI_ASSOC)){
echo $row['name']."<br>";
}
RESULT:
easy peasy<br>
fluff fluff<br>
From your comment: problem is that i can input the tag variable and if the tag variable is something that is not included in the database it shows nothing
That is because you are using an AND rather than an OR in the query. I corrected that also

Related

Dynamic value in sql query using php

I want to search a certain string in all the columns of different tables, so I am looping the query through every column name. but if i give it as dynamic value it does not seem to work.
what is wrong?
<?php
$search = $_POST['search'];
$columns = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'feedback'";
$columns_result = $conn->query($columns);
$columns_array = array();
if (!$columns_result) {
echo $conn->error;
} else {
while ($row = $columns_result->fetch_assoc()) {
//var_dump($row);
//echo $row['COLUMN_NAME']."</br>";
array_push($columns_array, $row['COLUMN_NAME']);
}
}
var_dump($columns_array);
$row_result = array();
for ($i = 0; $i < count($columns_array); $i++) {
echo $columns_array[$i] . "</br>";
$name = "name";
// $sql = 'SELECT * FROM feedback WHERE "'.$search.'" in ("'.$columns_array[$i].'")';
$sql = 'SELECT * FROM feedback WHERE ' . $name . ' like "' . $search . '"';
$result = $conn->query($sql);
if (!$result) {
echo "hi";
echo $conn->error;
} else {
foreach ($result as $row) {
array_push($row_result, $row);
echo "hey";
}
}
}
var_dump($row_result);
I am getting the column names of the table and looping through them because I have so many other tables which I need to search that given string. I don't know if it is optimal I did not have any other solution in my mind. If someone can tell a good way I will try that.
It looks to me that you want to generate a where clause that looks at any available nvarchar column of your table for a possible match. Maybe something like the following is helpful to you?
I wrote the following with SQL-Server in mind since at the beginning the question wasn't clearly tagged as MySql. However, it turns out that with a few minor changes the query work for MySql too (nvarchar needs to become varchar):
$search='%';$tbl='feedback';
if (isset($_POST['search'])) $search = $_POST['search'];
$columns = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = '$tbl' AND DATA_TYPE ='nvarchar'";
$columns_result = $conn->query($columns);
$columns_array = array();
if(!$columns_result) print_r($conn->errorInfo());
else while ($row = $columns_result->fetch(PDO::FETCH_ASSOC))
array_push($columns_array, "$row[COLUMN_NAME] LIKE ?");
$where = join("\n OR ",$columns_array);
$sth = $conn->prepare("SELECT * FROM $tbl WHERE $where");
for ($i=count($columns_array); $i;$i--) $sth->bindParam($i, $search);
$sth->execute();
$result = $sth->fetchAll(PDO::FETCH_ASSOC);
print_r($result);
The above is a revised version using prepared statements. I have now tested this latest version using PHP 7.2.12 and SQL-Server. It turned out that I had to rewrite my parameter binding part. Matching so many columns is not a very elegant way of doing queries anyway. But it has been a nice exercise.
It looks like you are using mysqli, so I wanted to give another way of doing it via mysqli.
It does more or less the same as cars10m solution.
$search = $_POST['search'];
$columns = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'feedback'";
$columns_result = $conn->query($columns)->fetch_all(MYSQLI_ASSOC);
// Here dynamically prepare WHERE with all the columns joined with OR
$sql = 'SELECT * FROM feedback WHERE ';
$arrayOfWHERE = [];
foreach($columns_result as $col){
$arrayOfWHERE[] = '`'.$col['COLUMN_NAME'].'` LIKE ?';
}
$sql .= implode(' OR ', $arrayOfWHERE);
// prepare/bind/execute
$stmt = $conn->prepare($sql);
$stmt->bind_param(str_repeat("s", count($arrayOfWHERE)), ...array_fill(0, count($arrayOfWHERE), $search));
$stmt->execute();
$result = $stmt->get_result();
$row_result = $result->fetch_all(MYSQLI_ASSOC);
var_dump($row_result);
Of course this will search for this value in every column of the table. It doesn't consider data type. And as always I have to point out the using PDO is better than mysqli. If you can switch to PDO.

SQL in php, make partial search using LIKE

I am trying to make SQL in php to return all the entries that matches a keyword that is entered by the user (from search bar).
I want to return all the entries that their name "partial" matches with the keyword.
I want at least to match the keyword, if an entry name in database before has space and after maybe another letter/space.
For example I have three entries with names "Milk", "Semi skimmed Milk" and "Full Milk 2". If the keyword is "Milk" or "milk" or "MiLK", I want to get all these three entries.
The only case I am thinking it might be the problem is case sensitive.
I tried with a keyword that exists exactly in database, but my app (on android) stops .
Based on user3783243 answer.
PHP FILE
<?php
$servername = "";
$username = "";
$password = "";
$dbname = "";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT name FROM items WHERE name LIKE CONCAT ('%', ?, '%')";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $keyword);
$res = $stmt->get_result();
while($row = $res->fetch_assoc()) {
echo $row["name"] . ",";
}
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
echo $row["name"] . ",";
}
} else {
echo "0";
}
$conn->close();
?>
Your query should be:
$sql = "SELECT * FROM items WHERE name LIKE CONCAT ('%', ?, '%')";
and then $keyword should be bound with whatever syntax the driver you are using supports.
As is your query would have been:
SELECT * FROM items WHERE name LIKE CONCAT ('%', Milk, '%')
and you wanted Milk to be a string so it needed to be quoted. As is mysql would have thought that was a column.
Alternatively you could do:
$keyword = '%' . $_POST['keyword'] . '%';
$sql = "SELECT * FROM items WHERE name LIKE CONCAT ?";
that is the same and still requires the binding though.
The binding also takes away the SQL injection. See How can I prevent SQL injection in PHP? and/or https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet#Defense_Option_1:_Prepared_Statements_.28with_Parameterized_Queries.29
Per update.. replace:
$keyword =$_POST['keyword'];
$sql = "SELECT * FROM items WHERE name LIKE '%$keyword%)";
$result = $conn->query($sql);
with:
$sql = "SELECT name FROM items WHERE name LIKE CONCAT ('%', ?, '%')";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $keyword);
$stmt->execute();
$res = $stmt->get_result();
if(empty($conn->errno) && !empty($res)) {
while($row = $res->fetch_assoc()) {
echo $row["name"] . ",";
}
} else {
echo '0';
//print_r($conn->errno);
}
$conn->close();
...
also remove
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
echo $row["name"] . ",";
}
} else {
echo "0";
}
$conn->close();
In this case you can convert the input in search bar to either upper or lower case by default then apply query in db like
For Upper case:
$keyword =strtoupper($_POST['keyword']);
$sql = "SELECT * FROM items WHERE upper(name) LIKE '%$keyword%)";
Or for lower case:
$keyword =strtolower($_POST['keyword']);
$sql = "SELECT * FROM items WHERE lower(name) LIKE '%$keyword%)";

You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1

I'm trying to save an id number in my database and I can't seem to store an integer inside the $resultid variable.
Here is my code:
<?php
if (isset($_POST['tittel'])) {
$meny = $_POST['meny'];
$tittel = $_POST['tittel'];
$innhold = $_POST['innhold'];
$con = mysqli_connect('localhost', 'root', '', 'vikerfjell');
if ($con) {
echo "Connected!";
"<br>";
} else {
die("Connection failed!");
}
$menyid = ("SELECT idmeny FROM meny WHERE tekst = '$meny'");
$resultid = mysqli_query($con, $menyid);
$resultarr = mysqli_fetch_assoc($resultid);
$query = "INSERT INTO innhold (tittel, tekst, idmeny) ";
$query. = "VALUES('$tittel', '$innhold', $resultarr)";
$result = mysqli_query($con, $query);
"<br>";
if (!$result) {
die('Query FAILED!'.mysqli_error($con));
}
}
mysqli_fetch_assoc- fetch a result row as an associative array, u need to select the key of the id u are tying to store
$menyid = ("SELECT idmeny FROM meny WHERE tekst = '$meny'");
$resultid = mysqli_query($con, $menyid);
$resultarr = mysqli_fetch_assoc($resultid);
$column_id=$resultarr['id_stored_on_db'];
$query = "INSERT INTO innhold (tittel, tekst, idmeny) ";
$query .="VALUES('$tittel', '$innhold', $column_id)";
Guessing $resultarr holds multiple idmeny, so you really have to loop through each idmeny and create multiple insert statements, as such:
$menyid = "SELECT idmeny FROM meny WHERE tekst = '$meny'";
$result = mysqli_query($con, $menyid);
while ($row = $result->fetch_assoc()) {
$query = "INSERT INTO innhold (tittel, tekst, idmeny) ";
$query .= "VALUES('$tittel', '$innhold', {$row['idmeny']})";
$result = mysqli_query($con, $query);
}
Found the problem. I missed a value in my dropdown code (another php file). Thanks anyway : )

PHP While Loops In While Loops not working

Hi I have had a long search for this but have found no fix.
My code is as follows:
$link = mysqli_connect("localhost",".........","...........",".........") or die("Error " . mysqli_error($link));
$ctime = time();
$check = "SELECT * FROM thread WHERE forumid='48' AND visible='1' ORDER BY lastpost DESC LIMIT 1" or die("Error in the consult.." . mysqli_error($link));
//execute the query.
$rc = mysqli_query($link, $check);
while($rows = $rc->fetch_assoc()){
$pid = $rows['firstpostid'];
$query = "SELECT * FROM dropouts WHERE date <= $ctime" or die("Error in the consult.." . mysqli_error($link));
//execute the query.
$result = mysqli_query($link, $query);
$row_cnt = $result->num_rows;
while($row = $result->fetch_array())
{
$date = $row['date'];
$user = $row['username'];
$sql = "DELETE FROM dropouts WHERE date = $date" or die("Error in the consult.." . mysqli_error($link));
//execute the query.
$done = mysqli_query($link, $sql);
//////////////////////////////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
$check1 = "SELECT * FROM post WHERE postid='$pid'" or die("Error in the consult.." . mysqli_error($link));
//execute the query.
$rc1 = mysqli_query($link, $check1);
while($row1 = $rc1->fetch_array())
{
$text = $row1['pagetext'];
echo str_replace($user, "", $text);
}
}
}
The problem is that when I run it like that I get no out put.
If I run it so that the while loops are not in eachother I get output but the script only does it for one row post/row.
Does anyone know how to fix this?
I read that it should work but this just isn't working...
Thanks
Have you tried echoing it. It can be that the query returns 0 or empty!
As a beginner in php, you may stumble into these kinds of issues. The best way to understand the problem would be to ECHO & EXIT. Check each step by doing this and you can better understand the problem.
In the problem above, instead of writing the entire code, first of all try checking the small portion of codes and remember:
The best compiler/interpreter lies between you two ears!!

How to make dynamic postgres prepared statements in PHP

I'm trying to make some prepared statements in PHP using postgres.
It's a bit difficult to explaing so i'll just show you:
$stmt = "SELECT * FROM customer WHERE zip = '$1'";
if(isset($_POST["CITY"])){
$stmt .= "AND city = '$2'";
}
if(isset($_POST["COUNTRY"])){
$stmt .= "AND country = '$3'";
}
$result = pg_prepare("myconnection", "my query", $stmt);
$result1 = pg_execute("myconnection","my query", array("0000","someCity","someCountry"));
Sorry if some of the code is wrong but it's a freehand example. What I need is to be able to make the prepared statement dynamic depending on if some variables isset/not-null.
It doesn't seem to work when posting 3 variables in the array when the statement only expects 1 or if i only need to add $1 and $3 but not $2. I hope you understand.
I need to use it this weekend, so I hope someone knows!
Thank you in advance!
In a prepared statement, the SQL is static on purpose. The number of parameters cannot vary once the statement is prepared.
But it'd be easy for your code to submit the right number of parameters depending on the statement. You could add a variable for the counter of parameters, and a dynamic php array to pass to pg_execute instead of hard-coded literals. And they would be incremented/populated inside the if (isset(...)) branches.
There is nothing wrong in having 3 different statements (one for each case) and execute the one that applies depending on the number of parameters passed.
Example:
EDIT: I modified the code to match all cases:
Only the zip specified
Zip + city
Zip + country
Zip + city + country
(even if there are some other cases, you'll understand the idea)
$stmt = "SELECT * FROM customer WHERE zip = '$1'";
if(isset($_POST["CITY"]) && isset($_POST["COUNTRY"])) {
$stmt3 = $stmt . " AND city = '$2'" . " AND country = '$3'";
} elseif(isset($_POST["CITY"])) {
$stmt1 = $stmt . " AND city = '$2'";
} elseif(isset($_POST["COUNTRY"])) {
$stmt2 = $stmt . " AND country = '$2'";
}
if(isset($stmt3)) {
$result = pg_prepare("myconnection", "my query", $stmt3);
$result1 = pg_execute("myconnection","my query", array("0000","someCity","someCountry"));
} elseif(isset($stmt2)) {
$result = pg_prepare("myconnection", "my query", $stmt2);
$result1 = pg_execute("myconnection","my query", array("0000","someCountry"));
} elseif(isset($stmt1)) {
$result = pg_prepare("myconnection", "my query", $stmt1);
$result1 = pg_execute("myconnection","my query", array("0000","someCity"));
} else {
$result = pg_prepare("myconnection", "my query", $stmt);
$result1 = pg_execute("myconnection","my query", array("0000"));
}
I omitted (just as you did) all the error checks for brevity.
Although both Daniel and aymeric are correct - no sense in testing twice, nor using numbers. See below:
$some_vars = array();
$some_vars[":zip"] = $_POST["ZIP"];
$stmt = "SELECT * FROM customer WHERE zip = :zip";
if(isset($_POST["CITY"])){
$some_vars[":city"] = $_POST["CITY"]);
$stmt .= " AND city = :city";
}
if(isset($_POST["COUNTRY"])){
$some_vars[":country"] = $_POST["COUNTRY"]);
$stmt .= " AND country = :country";
}
$result = pg_prepare("myconnection", "my query", $stmt);
$result1 = pg_execute("myconnection","my query", $some_vars);
Don't forget to sanitize and such.
Don't do string concatenation. Check if the parameters are set. If not set them to empty. Use a single query string:
$zip = $_POST["zip"];
$city = $_POST["city"];
$country = $_POST["country"];
if (!isset($zip)) $zip = '';
if (!isset($city)) $city = '';
if (!isset($country)) $country = '';
$stmt = "
select *
from customer
where
(zip = '$1' or '$1' = '')
and
(city = '$2' or '$2' = '')
and
(country = '$3' or '$3' = '')
";
$result = pg_prepare("myconnection", "my query", $stmt);
$result1 = pg_execute(
"myconnection",
"my query",
array($zip, $city, $country)
);
Each condition will only be enforced if the respective parameter is not the empty string.
The same logic could use the null value in stead of empty those columns contain empty strings that should be selected.

Categories