- ベストアンサー
MySQLのテーブル名を変数に置いた場合
- MySQLのテーブル名を変数に置いた場合、UPDATE文の実行時にエラーが発生する場合があります。
- テーブル名をPOSTデータから受け取る場合、テーブルの存在を確認する必要があります。
- 正常にUPDATEを実行するためには、テーブルの名前をセットする際に存在確認を行い、存在する場合のみUPDATE文を実行する必要があります。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
>> 「 Call to a member function execute 」 PDOStatementの生成に失敗しています。$stmtの値はFALSEになっているはずです。PDOを使うときは例外をスローする設定にし、PDOExceptionをCatchできるようにコーディングを行うのが常識です。1回1回prepare()やexecute()の返り値がFALSEになっていないかチェックするのって馬鹿馬鹿しいでしょう、ここは例外に任せておけばラクになります。 PHPでデータベースに接続するときのまとめ http://qiita.com/mpyw/items/b00b72c5c95aac573b71 PDO::ATTR_ERRMODE オプションの値を PDO::ERRMODE_EXCEPTION に設定するようにしてください。また、PDO::ATTR_EMULATE_PREPARES も FALSE にしておいたほうが基本的には正解です。型キャストまわりで気持ち悪い仕様が多いので。 生成に失敗する直接の原因ですが… >> $sql = "UPDATE `{$id_set}` SET no = ? WHERE id = ?"; $id_set におかしな値が入っているからでしょうね。 >> $id_set = $_POST["id"]; 絶対にやめてください。せっかくプリペアドステートメントを使ってるのに、POSTされた値を何の検証もせずしてテーブル名にそのままセットしてしまったらSQLインジェクション攻撃への対策が台無しになってしまいます。 既に他の回答者さんから提示がありますが、あらかじめ許可する値を $id_sets = array('1', '2', '3'); として配列に用意しておき、 if ( ____isset($_POST['result'], $_POST['id']) && ____false !== $key = array_search($_POST['id'], $id_sets, true) ) { ____$id_set = $id_sets[$key]; } とするなどの工夫が必要です。どうせキーが必要なら in_array よりは array_search を使っておいた方が正解でしょう。また、この前の自分の回答で手抜き仕様にしてしまって申し訳ないのですが、不正パラメータのチェックをもう少しちゃんと行ったほうがいいかもしれません。具体的には型の検証です。 $_GET, $_POSTなどを受け取る際の処理 http://qiita.com/mpyw/items/2f9955db1c02eeef43ea 単に配列が文字列として処理された場合には E_NOTICE を発生し文字列 "Array" に変化するだけで済むのですが、explodeに配列が渡されてしまった場合 E_WARNING を発生し、さらにその後のforeachまで E_WARNING を連続的に発生していろいろ問題が起きてしまうので、ここは厳密にチェックを行うべきだと思います。これらを考慮すると先ほどのifブロックは isset($_POST['result'], $_POST['id']) && is_string($_POST['result']) && false !== $key = array_search($_POST['id'], $id_sets, true) となりますね。 なお、「false !== 」を頭に持ってくるメリットしては、代入を同時に行う際に ( ) が1つ不要に点があるでしょう。 ○ false !== ($key = array_search($_POST['id'], $id_sets, true)) ○ false !== $key = array_search($_POST['id'], $id_sets, true) ○ ($key = array_search($_POST['id'], $id_sets, true)) !== false × $key = array_search($_POST['id'], $id_sets, true) !== false 最後の例だと !== の方が優先順位が高いために、 「array_search($_POST['id'], $id_sets, true) !== false」 の結果の True/False が $key に代入されてしまいます。 「false !== 」が問題ないのは、もし「false !== $key」が先に評価されてしまったとしたら、変数ではなく「値」に対する代入を行うことになり、この文自体が無効になるからです。PHP4のあるバージョン以降からは無効になる文のことを考慮して優先度を変化させてくれるようになったようです。
その他の回答 (2)
- yambejp
- ベストアンサー率51% (3827/7415)
わざわざセキュリティのためプリペアドで処理しているのに、 汚染されているPOSTデータをSQL文に取り込んでどうするの・・・ テーブル名のリストをつくって配列にいれて、受け取るのはテーブル名ではなく 数値などで受け取って該当するテーブル名を返すのが妥当 もちろん、in_arrayで該当する番号がない場合はSQLを実行しないような 分岐処理もわすれずに
お礼
ご回答をいただき、ありがとうございました。 参考になりました。
- chie65536(@chie65535)
- ベストアンサー率44% (8752/19860)
ご参考。 http://nanisiteruno.blog116.fc2.com/blog-entry-31.html $id_set = $_POST["id"]; にした時に、出来上がった「$sql」の中身をデバッグプリントしてみよう。 たぶん「$id_set」に「貴方が想定してない文字列」が入って来ている筈。 例えば「URIエンコードされてて、入れた文字列そのままじゃない」とか「末尾に改行コードが居る」とか「文字化けしている」とか。
お礼
UPDATEした際に、$_POST["id"]の値が空になっていたのが原因でした。 前のページからデータを引っ張ってきているものの、同ページ(ファイル)で idに値を投げていなので当然ですよね・・・。 ありがとうございました。参考になりました。
お礼
前回に引き続き、大変恐縮です。 UPDATEをする際に、$id_setに値が空になっていました。 同ファイル内でUPDATEさせる際に値を投げていなかったので、 単純にテーブルが存在しないという事になっていた様です。 >foreachまで E_WARNING を連続的に発生していろいろ問題が起きてしまう $_POST['result']が文字列かどうかのチェックをする必要があるということですね。 false !==を先に記述する意味も理解できました。 配列の格納から、値の検証まで一連の流れをご教示いただき、大変勉強になりました。 本当にありがとうございました。