- ベストアンサー
AND検索ができない理由と解決方法 | PHP・MYSQL初学者のためのAND検索
- PHP、MYSQLを始めたばかりの方がAND検索をする際に検索結果が思った通りに表示されない理由について解説します。
- AND検索を実装する際に、キーワードの処理が正しく行われていないため、意図しない結果が表示されることがあります。
- 解決方法として、クエリ設定時にキーワードの処理を適切に行うことが重要です。キーワードの前後にワイルドカードをつけるなどすると、正しいAND検索を実現することができます。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
あー!!すみません。見落としてました(自分でもtypoeし直してるのに)。 >$stmt->bindParam(sprintf(':word%d', $key), $word, PDO::PARAM_STR); bindParam(変数をバインドする)だとexecute()時点の$keyの内容になっていまします。bindValue(値をバインドする)ですね。 $stmt->bindValue(sprintf(':word%d', $key), $word, PDO::PARAM_STR); もしくは(bindParamを使うなら) $stmt->bindParam(sprintf(':word%d', $key), $arr[$key], PDO::PARAM_STR); です。
その他の回答 (2)
- agunuz
- ベストアンサー率65% (288/438)
>$dsn = 'mysql:dbname=sample; host=localhost'; DSNでcharsetを指定してください(utf8なら問題ないとは思いますが習慣としてやっておくべき)。 $dsn = 'mysql:dbname=sample; host=localhost; charset=utf8'; http://php.net/manual/ja/ref.pdo-mysql.connection.php >while($row = $stmt->fetch(PDO::FETCH_ASSOC)) >{print"<li>{$row['keyword']}{$row['title']}</li>";} >で結果を表示しようとしてできず、 とりあえず while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { print '<pre>'; var_dump($row); print '</pre>'; print '<hr>'; } とでもして、内容が正しいことを確認してください。 (蛇足) 出力はprintfを使って while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { printf('<li>%s %s</li>', $row['keyword'], $row['title']); } とした方が(変数を波括弧で括らずに済むので)楽だと思います。 http://php.net/manual/ja/function.printf.php
お礼
ご丁寧に、再びのご回答、本当にありがとうございます。 ゆっくりですが、解読できてきました。本当にすいません。 charsetの指定いたしました。 sprintf、とても勉強になりました。なるほど、これを使うんですね。 デバックは、 0:(keyword like :word0) 1:(keyword like :word1) ----- 0:%テ% 1:%サ% と、表示されており、代入する値は合っていると思われるのですが、 やはり、「テ」「サ」で検索するとBのデータが出てきてしまいます…… sqlでand検索すると、きちんと該当ゼロになるのですが、。 一番最後のキーワードのみで、検索してしまうようです。 (「テ」「ス」で検索してAテストのデータが出るのは「ス」が入っているのがAのみだからのようです……) <form action="sample2.php" method="GET"> <input type="text" name="q" size="20"> <input type="submit" value="search"> </form> <?php require_once 'dbmanager.php'; $pdo = getDb(); $q = filter_input(INPUT_GET, 'q'); if (isset($q)) { $words = explode(" ", str_replace(" ", " ", trim($q))); } else { $words = array(); } // 解析 $tmp = array(); $arr = array(); foreach($words as $key=>$word) { if ($word === '') { continue; } $tmp[$key] = sprintf('(keyword like :word%d)', $key); $arr[$key] = '%' . addcslashes($word, '\_%') . '%'; } // デバッグ用表示ここから print '<pre>'; foreach ($tmp as $key=>$val) { printf('%s:%s<br>', $key, htmlspecialchars($val, ENT_QUOTES)); } print '</pre><hr><pre>'; foreach ($arr as $key=>$val) { printf('%s:%s<br>', $key, htmlspecialchars($val, ENT_QUOTES)); } print '</pre>'; // デバッグ用表示ここまで if (count($tmp) > 0) { $sql = 'select * from ttables where ' . implode('and', $tmp) . ' order by id desc'; $stmt = $pdo->prepare($sql); foreach ($arr as $key => $word) { $stmt->bindParam(sprintf(':word%d', $key), $word, PDO::PARAM_STR); } $stmt->execute(); while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { printf('<li>%s %s</li>', $row['keyword'], $row['title']); } } else { $stmt = $pdo->query('select * from ttables order by id desc'); }
- agunuz
- ベストアンサー率65% (288/438)
>$pdo = getDb(); どういうDSNになっているか(提示されていないので)わかりませんが、charsetはキチンと設定されていますよね? >$q = htmlspecialchars($_GET['q']); //クエリを入力 こんなところでhtmlspecialcharsする意味がわかりません。$qを表示する記述がありません(使うとすれば「表示するときだけ」です)。 とりあえずデバッグ用の表示でも入れて「期待した内容になっているか」確認してください。 (例) <form action=""> <input type="text" name="q" size="20"> <input type="submit" value="search"> </form> <?php require_once 'dbmanager.php'; $pdo = getDb(); $q = fiulter_input(INPUT_GET, 'q'); if (isset($q)) { $words = explode(" ", str_replace(" ", " ", trim($q))); } else { $words = array(); } // 解析 $tmp = array(); $arr = array(); foreach($words as $key=>$word) { if ($word === '') { continue; } $tmp[$key] = sprintf('(keyword like :word%d)', $key); $arr[$key] = '%' . addcslashes($word, '\_%') . '%'; } // デバッグ用表示ここから print '<pre>'; foreach ($tmp as $key=>$val) { printf('%s:%s<br>', $key, htmlspecialchars($val, ENT_QUOTES)); } print '</pre><hr><pre>'; foreach ($arr as $key=>$val) { printf('%s:%s<br>', $key, htmlspecialchars($val, ENT_QUOTES)); } print '</pre>'; // デバッグ用表示ここまで if (count($tmp) > 0) { $sql = 'select * from ttables where ' . implode('and', $tmp) . ' oreder by id desc'; $stmt = $pdo->prepare($sql); foreach ($arr as $key => $word) { $stmt->bindParam(sprintf(':word%d', $key), $word, PDO::PARAM_STR); } $stmt->execute(); } else { $stmt = $pdo->query('select * from ttables oreder by id desc'); }
補足
お応え、ありがとうございます。 htmlspecialcharsは完全に勘違いしておりました。ご指摘ありがとうございます。 dbmanager.phpの内容は、 <?php function getDb(){ $dsn = 'mysql:dbname=sample; host=localhost'; $usr = 'user'; $psw = 'password'; try { $db = new PDO($dsn, $usr, $psw); } catch (PDOException $e) { exit('データベース接続失敗。'.$e->getMessage()); } return $db; } ?> です。 アドバイス通り直しましたところ、期待した内容にはなっているようです。 私の勉強が足らず、 while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {print"<li>{$row['keyword']}{$row['title']}</li>";} で結果を表示しようとしてできず、いただいた回答を解読するまで少し時間がかかりそうです。 本当にすいません。ありがとうございます。
お礼
あああ、確かに「bindParamメソッドによってバインドされた変数の内容は(バインドされたその瞬間ではなく)executeメソッドが呼び出されたタイミングで評価される」(p362,独習PHP)とありました……agunuzのお陰で、bindparaとbindvalueの違い理解できました。なるほど、そういうことだったんですね。 最後までお付き合いくださり、本当にありがとうございました!!!! 無事、できました!!! 本当に本当にありがとうございました><。