PHPプリペアドステートメントをどこで使えば良

Writer: admin Type: arte Date: 2019-01-08 00:00
PHPプリペアドステートメントをどこで使えば良いのか(初心者です)フォームの値でデータを抽出して表示させるPHPプログラムです。(項目内はOR、項目間はAND検索のSQL文作成)一応これで動いているのですが、フォームのデータを扱う場合はプリペアドステートメントを使うべきとのこと。この場合どこでプリペアするのが良いのか教えていただけますでしょうか。----ソース ここから$post_1 = $_POST['val_1'];$post_2 = $_POST['val_2'];$post_keyword = $_POST["keyword"];if (isset($post_1) && is_array($post_1)) { //未定義またはNULLではないか、また配列かどうか $post_1 = "'".implode("','", $post_1)."'"; //''でかこむ $val_1 = " field_1 IN ( $post_1 )"; //IN句を作る $sql[] = $val_1; //SQL文用の配列に追加}if (isset($post_2) && is_array($post_2)) { $val_2 = "'".implode("','", $post_2)."'"; $val_2 = " field_2 IN ( $val_2 )"; $sql[] = $val_2; }if (strlen($post_keyword)>0){ //キーワードが入力されていたら $post_keyword = htmlspecialchars($post_keyword,ENT_QUOTES); $post_keyword = str_replace(" "," ",$post_keyword); $array = explode(" ", $post_keyword); //キーワードをスペースで分割して配列に入れる //キーワードの数だけループしてLIKE句の配列を作る $keyword_condition = []; foreach($array as $keyword) { $keyword_condition[] = "concat(field_3, field4) LIKE '%$keyword%'"; } //これをANDでつなげて文字列にする $keyword_condition = implode(" AND ", $keyword_condition); $sql[] = $keyword_condition;}//SQL文の作成if(!empty($sql)){ $sql = "AND ".implode(" AND ", $sql); //条件をANDでつなぎ、先頭にもWHEREに続くANDを付ける}$re = $pdo->query("select * from works WHERE 1 $sql");---- ソースここまで$prepare = $pdo->prepare(?);としたいところですが、構文エラーです。$prepare = $pdo->prepare($pdo->query("select * from works WHERE 1 ?"));こちらは致命的エラー。そもそも SELECTでもプリペアドステートメントにするべきでしょうか。共感した0###>$post_1 = $_POST['val_1'];>$post_2 = $_POST['val_2'];>$post_keyword = $_POST["keyword"];いきなりこれはやめましょね・・・配列で処理していますから、プリペアドステートメントに疑問符パラメータをいくつ書けばいいかはわかりますよね?$data = [];$where = [];としておいて、if (count($post_1) > 0) {// データに$post_1を追加$data = array_merge($data, $post_1);// Field_1 用の条件式を生成$where[] = '( field_1 in (' . implode(', ', array_fill(0, count($post_1), '?')) . '))';}のようにデータを(疑問符パラメータがデータの個数分存在する)条件式を格納しておいて、$pdo->prepare('select * from works where ' . implode('and', $where));$pdo->execute($data);で実行すればいいと思いますが・・・ナイス0
###早速のご回答ありがとうございます。>$post_1 = $_POST['val_1'];これはなぜダメなのでしょう。分かりやすいように名前を変える意味で使っていました。$_POST['val_1']のまま使うほうが良いのですか?初心者すぎて申し訳ないです。もっと配列についても勉強する必要があるようです。(配列に限りませんが…)いただいたコードの意味をしっかり考えて、根本的に書き直します!具体的に提示していいただき助かりました。ありがとうございます。
###具体的にご提示いただきありがとうございました。本当に助かりました。教えていただいたことは今後のプログラミングにも生かしていきます!ネット上にはたくさんの先生がいらして心強いです。どうもありがとうございました。###PHPでデータベースに接続するときのまとめ - Qiita https://qiita.com/mpyw/items/b00b72c5c95aac573b71こちらに注意点から方法まで,今回の実装のための情報がすべてまとめられているので,ご一読ください。・LIKE検索・可変長プレースホルダのあたりですね。>> $post_keyword = htmlspecialchars($post_keyword,ENT_QUOTES); htmlspecialcharsの使いかたがおかしいです。「とりあえず使っておけば安全」みたいな発想は逆に危険なので,こちらも使うべきところを再確認してください。「何故htmlspecialcharsを通すのか?」を一言でどうぞ - Qiita https://qiita.com/mpyw/items/19e6fed835ccdbcb0d6dナイス0
###> そもそも SELECTでもプリペアドステートメントにするべきでしょうか。解決策は他で出ていると思うので、これの回答を。するべきです。何か大きな(致命的な)勘違いをされているかもしれないので、アプリケーション内にSQLを組み込む場合は、SQLインジェクションという攻撃手法についてよく理解されたほうがよいと思います。プリペアドステートメントにしなくてよいのは、動的に変わる値をSQLに組み込まない場合のみです。「1'; insert into ....; -- 」などが入っていた場合(かつ、PDOで複文実行が可能になっている場合)、任意のSQLコードが実行されることとなります。update, deleteなどでも同じです。短時間でシステムに致命的なダメージを与えられます。また、「1' OR 1 = 1; -- 」が入っていた場合、テーブル内の全データを抜き取られてしまいます。今回の質問の場合は前提が全行抽出なのでいいのですが、個人情報が入ったテーブルなどで、意図せず他ユーザーの情報が抜き取られてしまったりします。ナイス0

 

TAG