2009-11-23 4 views
40

Sto provando a eseguire una ricerca tramite la classe PDO di php (driver mysql). Ho la seguente interrogazione lavoro con il cliente di MySQL (i nomi delle tabelle cambiati per proteggere gli innocenti):Istruzione preparata PHP PDO - query MySQL LIKE

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; 

Questo funziona come un fascino a prescindere dal termine di ricerca che uso. Tuttavia, quando passo a php, non riesco a farlo restituire nulla. Ho provato diverse sintassi che sembrano logiche per funzionare, ma nulla di ciò che ho provato funziona. ecco il mio codice esistente:

$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(); 
} 

Ho provato quanto segue pure (clausola SQL WHERE & parazione> execute linee sono tutto ciò che cambia):

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.'%')); 

ecc ...

+1

potrebbe essere solo una questione di trasposizione, ma non hanno chiuso l'istruzione SQL - è necessario mettere un apostrofo (') alla fine di esso. –

+0

Si è trattato di un problema di recepimento. Se avessi dimenticato il 'Sono sicuro che PHP sarebbe completamente fuori di testa, lol. Grazie per la risposta estremamente rapida, però. – TIm

+1

Cosa ottieni quando var_dump() $ dbh, $ prep e $ ret? Sono valori che ti aspetti? Hai provato a eseguire la stessa query utilizzando la famiglia di funzioni mysql_ * per il confronto? – jkndrkn

risposta

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

Questo è sbagliato. Non hai bisogno delle virgolette.

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

Anche questo è sbagliato. Prova con:

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

Spiegazione: Le dichiarazioni preparate non solo fanno una stringa-sostituzione. Trasportano i dati completamente separati dalla query. Le quotazioni sono necessarie solo quando si incorporano i valori in una query.

+0

Grazie per questa spiegazione.Potrebbe non risolverlo, ma lo archiverò nella memoria per uso futuro. – TIm

+26

@Tlm dovresti ancora accettare la sua risposta. risponde alla tua domanda come fornita direttamente. Non ti costa nulla da accettare. –

-5

Bene, ho risolto questo. E francamente, sono un idiota ... Grazie a tutti per aver visto questo e dare un buon feedback. Il problema era un errore di battitura nel nome di una tabella (che ho cambiato, quindi nessuno qui sarebbe in grado di vedere il mio problema per cominciare ...). I suggerimenti mi hanno portato a trovare il problema, quindi, grazie adam, jkndrkn e troelskn.

Per la cronaca, la seguente combinazione funziona bene:

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

-1 Questo non è il modo corretto per farlo. Non dovresti * usare * CONCAT() per tre letterali stringa * statici *, in quanto ti apre fino a un tipo specifico di iniezione SQL (non ricordo il nome). –

+4

Non so chi siano tutte queste persone che hanno alzato il commento sopra, ma stranamente - nessuno di loro è riuscito a nominare l'iniezione. Probabilmente perché tale "iniezione" non è mai esistita. –

+0

Mi piacerebbe sentirlo da @ TheodoreR.Smith se è ancora nei dintorni di SO. [Più specificamente su questa domanda distinta] (http://stackoverflow.com/questions/22740375/why-should-you-not-use-concat-for-static-string-literals) – Prix

-2
$prep = $dbh->prepare($sql); 
$ret = $prep->execute(array('searchTerm' => $searchTerm)); 
+4

Questa anser non è completa (a cui $ sql ti riferisci?), Mi mancano alcune informazioni (come fare ".. LIKE '% FOO%'" ricerche?) E mancano alcune spiegazioni. Qualche codice messo così non è una risposta, IMO, è solo una cosa fuori contesto. – Redips77