41

I am trying to do a search through php's PDO class (mysql driver). I have the following query working with the MySQL client (table names changed to protect the innocent):

SELECT    hs.hs_pk, 
          hs.hs_text, 
          hs.hs_did, 
          hd.hd_did, 
          hd.hd_text, 
          hv.hv_text, 
          hc.hc_text 
FROM      hs 
LEFT JOIN hd 
 ON       hs.hs_did = hd.hd_did 
LEFT JOIN hd 
 ON       hd.hd_vid = hv.hv_id 
LEFT JOIN hc 
 ON       hd.hd_pclass = hc.hc_id
WHERE     hs.hs_text LIKE "%searchTerm%"
LIMIT 25;

This works like a charm regardless of the search term that I use. However, when I move to php, I can't get it to return anything. I have tried several different syntaxes that seem logical to work, but nothing I have tried works. here's my existing code:

$handle = fopen('/foo/bar/test.log', 'w+');
fwrite($handle, "doSearch, with search term: $searchTerm\n");
$sql = 
'SELECT   hs.hs_pk, 
          hs.hs_text, 
          hs.hs_did, 
          hd.hd_did, 
          hd.hd_text, 
          hv.hv_text, 
          hc.hc_text 
FROM      hs 
LEFT JOIN hd 
 ON       hs.hs_did = hd.hd_did 
LEFT JOIN hd 
 ON       hd.hd_vid = hv.hv_id 
LEFT JOIN hc 
 ON       hd.hd_pclass = hc.hc_id
WHERE     hs.hs_text LIKE :searchTerm
LIMIT 25';

try {
 $dbh = new PDO('mysql:host=localhost;dbname=awdb', "user", "password");
 fwrite($handle, "connected to DB\n");
 $prep = $dbh->prepare($sql);
 $ret = $prep->execute(array(':searchTerm' => '"%'.$searchTerm.'%"'));

 while ($row = $prep->fetch(PDO::FETCH_ASSOC)) {
  $i++;
  $result[$i]['subText'] = $row['hs_pk'];
  $result[$i]['subText'] = $row['hs_text'];
  $result[$i]['subDid'] = $row['hs_did'];
  $result[$i]['devDid'] = $row['hd_did'];
  $result[$i]['devText'] = $row['hd_text'];
  $result[$i]['vendorText'] = $row['hv_text'];
  $result[$i]['classText'] = $row['hc_text'];
 }
    $dbh = null;
}   
catch (PDOException $e) {
  print "Error!: " . $e->getMessage() . "<br/>";
  die();
}

I've tried the following as well (SQL WHERE clause & prep->execute lines are all that change):

WHERE hs.hs_text LIKE CONCAT(\'%\', ?, \'%\') 
$ret = $prep->execute(array($searchTerm));

WHERE hs.hs_text LIKE "%:searchTerm%" 
$ret = $prep->execute(array(':searchTerm' => $searchTerm));

WHERE hs.hs_text LIKE ":searchTerm" 
$ret = $prep->execute(array(':searchTerm' => '%'.$searchTerm.'%'));

etc...

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
TIm
  • 481
  • 1
  • 4
  • 6
  • 1
    It might just be a transpose issue, but you haven't enclosed your sql statement - you need to put an apostrophe (') at the end of it. – Adam Hopkinson Nov 23 '09 at 22:18
  • It was a transposition issue. If I had forgotten the ' I am sure PHP would have completely freaked out, lol. Thanks for the extremely quick reply, though. – TIm Nov 23 '09 at 22:27
  • 1
    What do you get when you var_dump() $dbh, $prep, and $ret? Are they values you expect? Have you tried running the same query using the mysql_* family of functions for comparison? – jkndrkn Nov 23 '09 at 22:41
  • Here is the var dump for each (as well as output from the script): doSearch, with search term: com connected to DB object(PDO)#32 (0) { } object(PDOStatement)#33 (1) { ["queryString"]=> string(586) "SELECT ...statement too large, but matches the $sql variable in the script... } bool(false) ret: Array ( ) result: should have added rows I haven't tried the mysql_* family of functions. I'll need to look up the docs as I am not as familiar with those. – TIm Nov 23 '09 at 22:50

3 Answers3

95
$ret = $prep->execute(array(':searchTerm' => '"%'.$searchTerm.'%"'));

This is wrong. You don't need the double quotes.

WHERE hs.hs_text LIKE ":searchTerm" 
$ret = $prep->execute(array(':searchTerm' => '%'.$searchTerm.'%'));

This is also wrong. Try with:

$prep = $dbh->prepare($sql);
$ret = $prep->execute(array(':searchTerm' => '%'.$searchTerm.'%'));

Explanation: Prepared statements don't simply do a string-replace. They transport the data completely separate from the query. Quotes are only needed when embedding values into a query.

troelskn
  • 115,121
  • 27
  • 131
  • 155
  • Thank you for that explanation. It may not solve this one, but I'll file it in my memory for future use. – TIm Nov 23 '09 at 23:22
  • 27
    @Tlm you still should accept his answer. it answers your question as provided directly. It doesn't cost you anything to accept. – Theodore R. Smith Sep 03 '10 at 01:19
-2
$prep = $dbh->prepare($sql);
$ret = $prep->execute(array('searchTerm' => $searchTerm));
Cat
  • 66,919
  • 24
  • 133
  • 141
Micah
  • 5
  • 1
  • 4
    This anser is not complete (to wich $sql do you refer?), is missimg some information (how to make ".. LIKE '%FOO%' " searches?) and is lacking of any explanation. Some code put like this is not an answer, IMO, is just an out of context thing. – Redips77 May 05 '15 at 10:37
-3

Well, I solved this one. And quite frankly, I'm an idiot... Thank you all for seeing this and giving good feedback. The problem was a typo in a table name (which I changed, so nobody here would be able to see my issue to begin with...). The suggestions did lead me to find the issue, though, so thank you adam, jkndrkn and troelskn.

For the record, the following combination works well:

WHERE aw_hcl_subdevices.hs_text LIKE CONCAT(\'%\', ?, \'%\')
$ret = $prep->execute(array($searchTerm));
TIm
  • 481
  • 1
  • 4
  • 6
  • 14
    -1 This is not the correct way to do this. You should *not* use CONCAT() for three *static* string literals, as it opens you up to a specific type of SQL injection (i forget the name). – Theodore R. Smith Sep 03 '10 at 01:20
  • 6
    Dunno who are all these people who upvoted the above comment, but strangely - none of them managed to name the injection. Probably because such "injection" never existed at all. – Your Common Sense Mar 30 '14 at 04:54
  • Would love to hear it from @TheodoreR.Smith if he is still around SO. [More specifically on this distinct question](http://stackoverflow.com/questions/22740375/why-should-you-not-use-concat-for-static-string-literals) – Prix Mar 30 '14 at 05:31
  • 2
    If you google "static string literals sql injection" this is the first result. – Mike Mar 30 '14 at 05:35
  • @Mike, mean you SO-question, produced by comment above? [This](http://stackoverflow.com/questions/22740375/why-should-you-not-use-concat-for-static-string-literals)? This looks like `The Bible said that all words in The Bible are true.` – vp_arth Dec 09 '14 at 09:33
  • @vp_arth Hah I don't remember what my point was. Anyway, [this one](http://stackoverflow.com/questions/22740375/why-should-you-not-use-concat-for-static-string-literals) is the first result, at least now. Meh. – Mike Dec 09 '14 at 18:00
  • This link was already in my comment above, under `This` word. And this SO-question asked by guy, which read @TheodoreR.Smith's comment above. Also I see now, that comment, which you answer has this SO-question link too. – vp_arth Dec 10 '14 at 05:26