I am trying to implement a search using php5 pdo and mysql. What I am trying to do is search for a given set of keywords in my table 'posts' and return records that contain any of the given keywords in the column 'title'. But it returns no result set even if I give keywords that I know exist in the table. I use collation 'utf8mb4_unicode_ci'. Here is my code:
<?php
if($_SERVER['REQUEST_METHOD']=='POST'){
$charset="utf8mb4";
$dsn="mysql:host=$host;dbname=$db;charset=$charset";
$opt=[ PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC,
PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION];
$pdo=new PDO($dsn,$user,$pass,$opt);
$keywords=$_POST['keywords'];
$keywordArray=explode(' ',$keywords);
$n=count($keywordArray);
$query="SELECT * FROM posts WHERE title LIKE ?";
$keywordArray[0]="'%".$keywordArray[0]."%'";
for($i=1;$i<$n;$i++){
$keywordArray[$i]="'%".$keywordArray[$i]."%'";
$query=$query." OR title LIKE ?";
}
$query=$query." LIMIT 50;";
echo $query;
$stmt=$pdo->prepare($query);
$stmt->execute($keywordArray);
$res=$stmt->fetchAll();
echo "<br><h1>SEARCH RESULTS:</h1><br><ul>";
if($res){
foreach($res as $row){
echo "<li>".$row['date']."".$row['title']."</li><br>";
}
}
else{
echo "<h2 style=\"color:red;\">No results!</h2>";
}
echo "</ul></div>";
}
?>
Its working inside the console.
SELECT * FROM posts WHERE title LIKE '%hit%' OR title LIKE '%fifa%';
returns two rows. But searching with 'hit fifa' using the form returns zero rows.
Since you are using prepared statements, you don't need the single quotes around your expression. Change your code, removing those quotes, to
$query="SELECT * FROM posts WHERE title LIKE ?";
$keywordArray[0]="%".$keywordArray[0]."%";
for($i=1;$i<$n;$i++){
$keywordArray[$i]="%".$keywordArray[$i]."%";
$query.=" OR title LIKE ?";
}
It was treating the quote marks as being part of the value inside the parameter. So you would have ended up with SQL something like
SELECT * FROM posts WHERE title LIKE '\'%Something%\''
and clearly this won't match, because the values in the database won't have single quotes at the start and end in most cases.
With the changes, it should translate into SQL like this
SELECT * FROM posts WHERE title LIKE '%Something%'
This is because the parameterisation process handles the quoting and escaping job automatically for you - it's one way in which it protects against SQL injection attacks ( and also, incidentally, against syntax errors caused by erroneous / unescaped quote marks).
P.S. If a request is ever submitted to this code where no keyword at all was provided, then the code will crash because it assumes there is always a value in $keywordArray[0]. Consider revising this to either validate that a keyword was provided, or just loop the whole array and, if no keywords are submitted, simply don't add a WHERE clause to the query at all.
Related
I have a loop that is producing a string like $sku = MAR-9-870-2-L. I have a database that is a list of "skusearchquery" that often look like skusearchquery = MAR-9. I am trying to do a search for all rows of the database that have a skusearchquery contained inside the string $sku.
I know the code below doesn't work because MAR-9-870-20-L is NOT LIKE MAR-9-870 because MAR-9-870 doesn't contain the longer string, so I'm wondering how I can say: if the row value skusearchquery matches part of the string MAR-9-870-20-L, then select it.
$search = mysqli_query($connect, "SELECT * FROM skusearch WHERE skusearchquery LIKE '%$sku%'");
Please try the LOCATE() function:
$search=mysqli_query($connect,"SELECT * FROM skusearch WHERE LOCATE(`skusearchquery`,'$sku'");
...if this tests positively, you should take tadman's advice and protect your query.
As you said, that your searchquery field can have smaller part of sku then you can try below query to get those results as well
$search = mysqli_query($connect, "SELECT * FROM skusearch WHERE skusearchquery LIKE '%$sku%'" or '$sku' like concat('%',skusearchquery,'%');
Also make sure to protect your queries from sql injection as suggested by #tadman.
Answer found (syntax): The column name of my string had to be encased in backticks " ` " as they contained spaces. Note that this means that the majority of this post has no relevance to the issue. The code has been corrected in case someone wants to do something similar.
So, I am doing a foreach loop to assign a value (1/0) to non-static columns in my database (it needs to support addition/deletion/editing of columns). I am using $connectionvar->query($queryvar); to do my queries which worked fine up until now when I'm trying to use a custom built string as $queryvar in order to change the column name to a variable within the loop. I've been outputting this string through echo and it looks exactly like my functional queries but somehow doesn't run. I've attempted to use eval() to solve this but to no avail (I feel safe using eval() as the user input is radio buttons).
Here's the loop as well as my thought processes behind the code. If something seems incoherent or just plain stupid, refer to my username.
foreach($rdb as $x) { //$rdb is a variable retrieved from $_POST earlier in the code.
$pieces = explode("qqqppp", $x); //Splits the string in two (column name and value) (this is a workaround to radio buttons only sending 1 value)
$qualname = $pieces[0]; //Column name from exploded string
$qualbool = $pieces[1]; //desired row value from exploded string
$sql = 'UPDATE users SET '; //building the query string
$sql .= '`$qualname`';
$sql .= '=\'$qualbool\' WHERE username=\'$profilename\''; //$profilename is retrieved earlier to keep track of the profile I am editing.
eval("\$sql = \"$sql\";"); //This fills out the variables in the above string.
$conn->query($sql); //Runs the query (works)
echo ' '.$sql.' <br>'; //echoes the query strings on my page, they have the exact same output format as my regular queries have.
}
}}
Here's an example of what the echo of the string looks like:
UPDATE users SET Example Qualification 3='1' WHERE username='Admin2'
For comparison, echoing a similar (working) query variable outside of this loop (for static columns) looks like this:
UPDATE users SET profiletext='qqq' WHERE username='Admin2'
As you can see the string format is definitely as planned, yet somehow doesn't execute. What am I doing wrong?
PS. Yes I did research this to death before posting it, as I have hundreds of other issues since I started web developing a month ago. Somehow this one has left me stumped though, perhaps due to it being a god awful hack that nobody would even consider in the first place.
You need to use backticks when referring to column names which have spaces in them. So your first query from the loop is outputting as this:
UPDATE users SET Example Qualification 3='1' WHERE username='Admin2'
But it should be this:
UPDATE users SET `Example Qualification 3`='1' WHERE username='Admin2'
Change your PHP code to this:
$sql = 'UPDATE users SET `'; // I added an opening backtick around the column name
$sql .= '$qualname`'; // I added a closing backtick around the column name
$sql .= '=\'$qualbool\' WHERE username=\'$profilename\'';
Example Qualification 3 : Is that the name of your Mysql Column name ?
You shouldnt use spaces nor upper / lower case in your columnname.
Prefere : example_qualification_3
EDIT :
To get column name and Comment
SHOW FULL COLUMNS FROM users
Hi There I'm trying to get some data with this SELECT statement and when I just select two items it gives me result but when I place third item it doesn't give any result.
$Query="SELECT * from tableName WHERE status='true' AND gid='".$gid."' AND section='".$cid."'";
Plz any solution.
this one works fine, but when I add third item status='true'. doesn't work.
$Query="SELECT * from tableName WHERE gid='".$gid."' AND section='".$cid."'";
First, let me say this: Double-quoted strings can parse your variables, so this line can work, too:
$Query="SELECT * from tableName WHERE gid='$gid' AND SECTION='$cid'";
Try to learn PHP basics about using single ' and double " quotes here: What is the difference between single-quoted and double-quoted strings in PHP?
Related to the database query, is status field is present in your database table? If not, it should NOT be included within the database, or it will return FALSE boolean value. Instead, use IF if you want to be 'selectively' filtering the status of the table.
if('your conditions here'){
$query = "SELECT * FROM tableName WHERE gid='$gid' AND section='$cid'";
}
I think your mistake is the status='true'
probable the database control its field with 1 or 0 value.
$content is a variable with a 'detailed description'.
product_id is column which might contain a substring of the detailed description ($content) in a MySQL table called products
I am trying to create a select statement that would find a record if the product_id is CONTAINED in the $content variable. Then I want to update another table called receive_sms with the url field from the SELECT staement
Researching on the website I have come up with the following.... But it doesn't work
$mysqlic = mysqli_connect("testsms.cloudaccess.net", "username", "password", "testsms2");
$prod_res=mysqli_query($mysqlic,"SELECT url from products
WHERE %product_id% LIKE %$content%");
mysqli_query($mysqlic,"INSERT INTO recieve_sms (comments) VALUES ('$prod_res')");
Any Ideas??
It should be:
$prod_res = mysqli_query($mysqlic, "SELECT url from products
WHERE '$content' LIKE CONCAT('%', product_id, '%')");
or:
$prod_res = mysqli_query($mysqlic, "SELECT url from products
WHERE LOCATE(product_id, '$content') != 0");
You need to put $content in quotes.
Actually, it would be better if you used a prepared query, then '$content' would become a placeholder ?.
After you query, you need to call mysqli_fetch_assoc() to get the column value:
$row = mysqli_fetch_assoc($prod_res);
$url = $row['url'];
Well, first of all, I don't understand why you're using wildcards on you field name. You want to check if a value is contained within the value of that field, consider changing this:
... WHERE %product_id% LIKE %$content%);
to
... WHERE product_id LIKE '%$content%');
Also, please, use prepared statements to avoid SQL injection. You're using MySQLi, which supports them.
EDIT
Also, the return of a mysqli_query is a MySQLi Resource. You'll have to fetch the results from the resource to gain access to the value you're looking for.
In model query -
public function get_articles_from_query($squery){
$query = DB::query(Database::SELECT, 'SELECT * FROM ieraksti WHERE virsraksts = "%:squery%" AND slug = "%:squery%" AND saturs = "%:squery%"')
->parameters(array(":squery" => $squery))->execute();
return $query;
}
Why this script is not working? I not have any errors, but blog articles not found.
Well, my first question is:
Do you have any rows that have that word, and nothing else, surrounded by % characters, in all three of the the title, content and slug (a)? This seems unlikely.
If not, the query will return no rows.
The use of the % wildcards is for like, not for =. If your squery word is banāns for example, your query will only match rows where all three columns are exactly the literal %banāns% value, not a value containing banāns somewhere within it.
I think you want:
SELECT * FROM ieraksti
WHERE virsraksts like "%:squery%"
AND slug like "%:squery%"
AND saturs like "%:squery%"
For your subsequent problem:
I understand the problem. I put in model var_dump($query); and it shows the query - SELECT * FROM ieraksti WHERE virsraksts like "%'ar'%" OR slug like "%'ar'%" OR saturs like "%'ar'%. The is not word 'ar', but ar. How to remove ' from query?
If that's the case, you will have to change your query to something like:
$query = DB::query(Database::SELECT,
'SELECT * FROM ieraksti WHERE virsraksts like :squery AND slug ...')
->parameters(array(":squery" => "%$squery%"))->execute();
In other words, move the attachment of the % characters to the parameter specification, not the query itself. From your debug, the parameters are automatically having single quotes wrapped around them so, if you want to do anything inside those quotes, you have to do it before the wrapping.
And you obviously don't need the double quotes in this case because that wrapping is taking place.
And check that line with "%$squery%" in it, I'm not sure it's the right syntax. I'd say my PHP was a bit rusty but, to be honest, I've only ever used it for about seven minutes in my whole life :-)
What you're aiming for is a string consisting of %, the value of $squery and another %.
(a) Man tiešām patīk, kā Google Translate padara mani izskatās es zinu desmitiem dažādās valodās :-)