LIKE query is unable to retrieve data, why? - php

This query is unable to retrieve any data from MySQL for reasons I cannot figure out after countless hours..
public function search()
{
if(isset($_GET['search']))
{
$searchTerms = trim(strip_tags($_GET['search']));
$sth = $this->db->prepare("SELECT COUNT(*) FROM articles WHERE (article_content LIKE :search) OR (article_title LIKE :search)");
$sth->execute( array(':search' => '%' . $searchTerms . '%') );
if($sth->fetchColumn() > 0)
{
while($row = $sth->fetchAll(PDO::FETCH_ASSOC))
{
return "search results: " . $row['article_title'];
return "" . $row['article_content'];
}
} else {
echo "No results.";
}
}
}
No matter what keyword I type in the form it always returns "No results.". What could be the issue because from what I can see it should work..
Selecting all rows from the table structure and counting so that fetchColumn can be runned, it is selecting from the correct table (articles), where article_content and article_title are both rows in the table, so what is the issue?

$sth->execute(array(':search' => '%'.$searchTerms.'%'));
Should be:
$sth->execute(array(':search' => '\'%\' + \''.$searchTerms.'\' + \'%\''));

Each bind var needs to be an individual bind var, even when named, and even when they both contain the same value:
$sth = $this->db->prepare(
"SELECT COUNT(*)
FROM articles
WHERE (article_content LIKE :search1)
OR (article_title LIKE :search2)"
);
$sth->execute(
array(
':search1' => '%' . $searchTerms . '%',
':search2' => '%' . $searchTerms . '%'
)
);

Try this:
$sth = $this->db->prepare("SELECT COUNT(*) FROM articles WHERE (article_content LIKE :search0) OR (article_title LIKE :search1)");
$searchstring="%" . $searchTerms . "%";
$sth->execute( array(':search0' =>$searchstring ,':search1'=>$searchstring) );
pdo fails to retrieve values when the same placheholder is repeated in a query with LIKE in it.

Related

how to perform a multi sql search via php in one field

i am using this sql search to find a title and artist in my database. I have on field containing infos like "ref.1570 title artist.mp4". When I do the search it works but in one direction only, i would like to get the result whatever the order i do the search... to be more precise if i search "title artist" no problem i found it. If i search "artist title" no way ... how can you help me making php sql search both directions ?
Best regards and thank you for your help.
Phil
i am using this code :
if ($search != null) {
$sql = 'SELECT * FROM `catalog` WHERE (`file`LIKE "%' . $search . '%")';
$sqlCount = 'SELECT count(*) FROM `catalog` WHERE (`file`LIKE "%' . $search . '%")';
}
Why don't you split keyword $search with space and append with Like statement in the query. Eg:
if ($search != null) {
$keywords=explode(" ",$search);
$sql = 'SELECT * FROM `catalog` WHERE 1=1'; // just to append OR condition.This won't affect anything as the condition will always be true.
$sqlCount = 'SELECT count(*) FROM `catalog` WHERE 1=1 ';
foreach($keywords as $key){
if(!empty($key)){
$sql.=' And file Like \'%'.$key.'\%';
$sqlCount.=' And file Like \'%'.$key.'\%';
}
}
}
I believe this will work as you expected.
I think you won't get around a foreach:
if ($search != null) {
$arrayOfSearchTerms = explode(' ', $search);
$sql = 'SELECT * FROM `catalog` WHERE ';
$sqlCount = 'SELECT count(*) FROM `catalog` WHERE ';
$termNumber = 0;
foreach ($arrayOfSearchTerms as $term) {
$addingSql = '';
if ($termNumber > 0) {
$addingSql = ' OR ';
}
$addingSql .= '(`file` LIKE "%') . $term . '%")';
$sql .= $addingSql;
$sqlCount = $addingSql;
$termNumber++;
}
}
You need to iterate over your search terms and add this terms into your 'LIKE'-Statement
you can try this research: it does a LIKE %word% for every word. If you want more powerfull research you should use tools like elasticsearch etc...
This way you could do:
$parts = explode(" ",$search)
$queryParts = array();
foreach ($parts as $part) {
$queryParts[] = `artist`LIKE "%' . $part . '%" ;
}
// this way we can have like %artist% AND like %title%
$querySearch= implode(" AND ", $queryParts);
$sql = 'SELECT * FROM `catalog` WHERE (". $querySearch .")';
$sqlCount = 'SELECT count(*) FROM `catalog` WHERE (`". $querySearch .")';
you have solved my problem i know now hos to correctly explode a request into variables ..
$search = $name;
$explode=explode(" ",$search);
print_r (explode(" ",$explode));
and then i use my sql request like this
$sql = 'SELECT * FROM `catalog` WHERE (`idc` LIKE "%' . $search . '%" OR `file` LIKE "%' . $search . '%" OR `title` LIKE "%' . $explode[0] . '%" AND `artist`LIKE "%' . $explode[1] . '% " OR `artist`LIKE "%' . $explode[0] . '%" AND `title`LIKE "%' . $explode[1] . '%")';
and it is working !
COOL
Use the multi query functions,
in mysqli should be : mysqli_multi_query();
More info on : Mysqli Multiquery

PHP: How to pass multiple values to SELECT query

I am new to PHP and hope someone can help me with this.
I currently use the below lines to retrieve a value from a db and to output it as an array with the item's ID and value which works as intended.
Now I would need to do the same for multiple items so my input ($tID) would be an array containing several IDs instead of just a single ID and I would need the query to do an OR search for each of these IDs.
I was thinking of using a foreach loop for this to append " OR " to each of the IDs but am not sure if this is the right way to go - I know the below is not working, just wanted to show my thoughts here.
Can someone help me with this and tell me how to best approach this ?
My current PHP:
$content = "";
$languageFrm = $_POST["languageFrm"];
$tID = $_POST["tID"];
$stmt = $conn->prepare("SELECT tID, " . $languageFrm . " FROM TranslationsMain WHERE tID = ? ORDER BY sortOrder, " . $languageFrm);
$stmt->bind_param("s", $tID);
$stmt->execute();
$result = $stmt->get_result();
while($arr = $result->fetch_assoc()){
$content[] = array("ID" => $arr["tID"], "translation" => $arr[$languageFrm]);
}
My thought:
foreach($tID as $ID){
$ID . " OR ";
}
Many thanks for any help,
Mike
There are two approaches, assuming $tID is an array of IDs
Using MySQL IN() clause
This will work also when $tID is not an array, but a single scalar value.
$tID = array_map('intval', (array)$tID); // prevent SQLInjection
if(!empty($tID)) {
$query .= ' WHERE tID IN(' . implode(',', $tId) . ')';
} else {
$query .= ' WHERE 0 = 1';
}
Using OR clause, as you suggested
A bit more complicated scenario.
$conds = array();
foreach($tID as $ID) {
$conds[] = 'tID = ' . intval($ID);
}
if(!empty($conds)) {
$query .= ' WHERE (' . implode(' OR ', $conds) . ')';
} else {
$query .= ' WHERE 0 = 1';
}
As per above conditions you can try with implode();
implode($tID,' OR ');
You can also use IN condition instead of OR something like this.
implode($tID,' , ');

Wordpress: wpdb prepare with conditional variable

I currently have a table. If the user searches for something, I would like the query to return the filtered results. If the user doesn't search for something, it should return all results. I'm not too sure how to do this with wpdb prepare.
if($search_query!=="all") {
$search_query = '%' . $search_query . '%';
$where = 'WHERE column_name LIKE %s';
}
$results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}table_name ".$where." ORDER BY id DESC LIMIT %d, %d", $search_query,$current_page,$rows_per_page));
Right now nothing returns when the search field is empty because the query is erroring out because it's throwing the parametrization off and passing $search_query to the %d beside LIMIT. Is it possible to make this variable conditional? Is there a way to do this without an IF statement ?
It looks like you can pass an array to prepare, as well as a list of variables, according to the WordPress documentation
That means that you could do something like this:
$where = "";
$parameters = array($search_query,$current_page,$rows_per_page);
if($search_query!=="all") {
array_push($parameters, '%' . $search_query . '%');
$where = 'WHERE column_name LIKE %s';
}
$results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}table_name ".$where." ORDER BY id DESC LIMIT %d, %d", $parameters));
Your WHERE clause will be empty if there's no data, so concatenating it into your query won't cause issues.
Why not do the prepare in the "If" statement? You can then do the other prepare (without the where clause) in the "Else" and just use the get_results on the proper prepared query?
if($search_query!=="all") {
$search_query = '%' . $search_query . '%';
$where = 'WHERE column_name LIKE %s';
$prepared = $wpdb->prepare("SELECT * FROM {$wpdb->prefix}table_name ".$where." ORDER BY id DESC LIMIT %d, %d", $search_query, $current_page, $rows_per_page) ;
} else {
$prepared = $wpdb->prepare("SELECT * FROM {$wpdb->prefix}table_name ORDER BY id DESC LIMIT %d, %d", $current_page, $rows_per_page);
}
$results = $wpdb->get_results($prepared);
You can escape the like parameter yourself and add it as a where clause if needed like this:
function like($str)
{
global $wpdb;
return "'" . '%' . esc_sql($wpdb->esc_like($str)) . '%' . "'";
}
if($search_query!=="all") {
$where = 'WHERE column_name LIKE ' . like($search_query);
}
and remove the search_query param from the prepared statement

PDO LIKE query not returning results

Well, I've been at this for a few hours, and for the life of me I can't figure out what is wrong. The code is as follows:
$str = "%" . $_POST['str'] . "%";
$offset = (int) $_POST['offset'];
try {
$stmt = $dbh->prepare("SELECT * FROM Spells WHERE :col LIKE :str ORDER BY :sort LIMIT 10 OFFSET :offset");
$stmt->bindParam(":col",$_POST['col']);
$stmt->bindParam(":str",$str);
$stmt->bindParam(":offset",$offset, PDO::PARAM_INT);
$stmt->bindParam(":sort",$_POST['sort']);
$stmt->execute();
}
catch (PDOException $e) {
echo "MySQL error: " . $e->getMessage() . "<br/>";
die();
}
The connection to the database works fine, no errors occur. If I type in % into the search field(which would be output as %%% in the query), results return as expected.
I've attempted the same query in phpMyAdmin and it works fine. I've been updating this script from the deprecated mysql_* functions, which worked fine before.
Example of the previous, deprecated query:
$sql = "SELECT * FROM Spells WHERE " . $col . " LIKE '%" . $str . "%' ORDER BY " . $sort . " LIMIT 10 OFFSET " . $offset;
As I may have already stated, I've been searching on this site as well, trying to find a solution; nothing has worked, not even MySQL's CONCAT('%',:str,'%').
The server I'm testing this on is running off of php version 5.3.17.
My question, in case I did not make it clear, is what am I doing wrong here? For those wondering(I thought that I put this but apparently I did not), there are no error messages.
The issue is that you cannot use parameters in place of identifiers. This means you cannot parameterise column or table names.
What your query essentially looks like when it is executed is
SELECT * FROM Spells WHERE 'some_column_name' LIKE '%something%'...
I would establish a whitelist of search and sort column names and use those to construct your query. Here's a very simple example
$search = array('col1', 'col2', 'col3');
$defaultSearch = 'col1';
$sort = array('col1', 'col2');
$defaultSort = 'col1';
$col = in_array($_POST['col'], $search) ? $_POST['col'] : $defaultSearch;
$sort = in_array($_POST['sort'], $sort) ? $_POST['sort'] : $defaultSort;
$sql = sprintf('SELECT * FROM Spell WHERE %s LIKE :str ORDER BY %s LIMIT 10 OFFSET :offset',
$col, $sort);
$stmt = $dbh->prepare($sql);
// bind :str and :offset, and so on

I want my search to only show results with matching field values. How is this done?

I want my search to only display results that match values in the same row.
I have two search fields:
'search' and 'search term'
the field names in my database are
name
lastname
email
So for example:
If i search
'mike' in 'search' and 'smith' in 'search term' the only results I want to show are results that match 'mike smith' NOT showing results like 'mike harris'
How is this achieved?
Thanks!
James
<?php
$conn = mysql_connect("", "", "");
if (!$conn) {
echo "Unable to connect to DB: " . mysql_error();
exit;
}
$search = addcslashes($search,'%_');
$searchterm = addcslashes($searchterm,'%_');
$search = "%" . $_POST["search"] . "%";
$searchterm = "%" . $_POST["searchterm"] . "%";
if (!mysql_select_db("")) {
echo "Unable to select mydbname: " . mysql_error();
exit;
}
$search = $_POST['search'];
$searchterm = $_POST['searchterm'];
$sql = "SELECT name,lastname,email
FROM test_mysql
WHERE name LIKE '%". mysql_real_escape_string($search) ."%'";
$result = mysql_query($sql);
if (!$result) {
echo "Could not successfully run query ($sql) from DB: " . mysql_error();
exit;
}
if(empty($_GET['search'])){ // or whatever your field's name is
echo 'no results';
}else{
performSearch(); // do what you're doing right now
}
if (mysql_num_rows($result) == 0) {
echo "No rows found, nothing to print so am exiting";
exit;
}
while ($row = mysql_fetch_assoc($result)) {
echo '<br><br><div class="data1">';
echo htmlentities($row["name"]);
echo '</div><br><div class="data2">';
echo htmlentities($row["lastname"]);
echo '</div><br><div class="data3">';
echo htmlentities($row["email"]);
echo '</div>';
}
mysql_free_result($result);
?>
Change:
WHERE name LIKE '%". mysql_real_escape_string($search) ."%'";
To:
WHERE name LIKE '%". mysql_real_escape_string($search) ."%' AND lastname LIKE '%". mysql_real_escape_string($search) ."%'";
$sql = "SELECT name,lastname,email
FROM test_mysql
WHERE name LIKE '%". mysql_real_escape_string($search) ."%'
AND name LIKE '%". mysql_real_escape_string($searchterm) ."%'";
Additionally, as I look over your query you may want to consider matching against last name as well. Your example suggested you may be looking for a first and last name, yet the query is only comparing name.
I often create a field called "search" in my searchable tables then set them as full text index so I can use mysql MATCH AGAINST for a more robust search option.
http://dev.mysql.com/doc/refman/5.5/en/fulltext-search.html
It was a while into my php development before I learned about match against. Certainly would have been beneficial to know early on. Hope it helps.
Change:
$search = addcslashes($search,'%_');
$searchterm = addcslashes($searchterm,'%_');
$search = "%" . $_POST["search"] . "%";
$searchterm = "%" . $_POST["searchterm"] . "%";
To:
$search = "%" . addcslashes($_POST["search"],'%_'). "%";
$searchterm = "%" . addcslashes($_POST["searchterm"],'%_'). "%";

Categories