お世話になります。
jQueryのプラグインを使用してDBから吐き出したデータを並べ替えをして、
UPDATEをさせているのですが、UPDATE先のテーブル名を変数に置いた場合、
例えば、
$id_set = "1";
if (isset($_POST['result'])) {
$sql = "UPDATE `{$id_set}` SET no = ? WHERE id = ?";
$stmt = $conn->prepare($sql);
foreach (explode(',', $_POST['result']) as $i => $id) {
$stmt->execute(array(++$i, $id));
} //foreachの終了
} //if (isset($_POST['result'])) の終了
$sql1 = "SELECT id, name, price, no FROM `{$id_set}` ORDER BY no";
$stmt = $conn->prepare($sql1);
$stmt->execute();
foreach ($stmt as $row) {
$state[] = array("id"=>$row['id'], "name"=>$row['name'], "price"=>$row['price'], "no"=>$row['no']);
$this->smarty_obj->assign("state_loop",$state);
} //foreachの終了
とすれば、「 1 」というテーブルのデータをSELECTしてUPDATEと正常に走るのですが、
$id_set = $_POST["id"];
等としてpostした場合、UPDATEの際に「 Call to a member function execute 」のエラーが
吐かれます。該当のテーブルが存在しないと認識されているのだと思いますが、
ページ遷移してくる際に持ってきたデータを活用してテーブル名にセットして、
尚且つ正常にUPDATEさせるにはどの様な構文にすれば良いのでしょうか?
ご教示の程、どうぞよろしくお願い申し上げます。
----------------
▼スペック
PHP 5.3.3
MySQL 5.0.95
----------------
No.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のあるバージョン以降からは無効になる文のことを考慮して優先度を変化させてくれるようになったようです。
前回に引き続き、大変恐縮です。
UPDATEをする際に、$id_setに値が空になっていました。
同ファイル内でUPDATEさせる際に値を投げていなかったので、
単純にテーブルが存在しないという事になっていた様です。
>foreachまで E_WARNING を連続的に発生していろいろ問題が起きてしまう
$_POST['result']が文字列かどうかのチェックをする必要があるということですね。
false !==を先に記述する意味も理解できました。
配列の格納から、値の検証まで一連の流れをご教示いただき、大変勉強になりました。
本当にありがとうございました。
No.2
- 回答日時:
わざわざセキュリティのためプリペアドで処理しているのに、
汚染されているPOSTデータをSQL文に取り込んでどうするの・・・
テーブル名のリストをつくって配列にいれて、受け取るのはテーブル名ではなく
数値などで受け取って該当するテーブル名を返すのが妥当
もちろん、in_arrayで該当する番号がない場合はSQLを実行しないような
分岐処理もわすれずに
No.1
- 回答日時:
ご参考。
http://nanisiteruno.blog116.fc2.com/blog-entry-3 …
$id_set = $_POST["id"];
にした時に、出来上がった「$sql」の中身をデバッグプリントしてみよう。
たぶん「$id_set」に「貴方が想定してない文字列」が入って来ている筈。
例えば「URIエンコードされてて、入れた文字列そのままじゃない」とか「末尾に改行コードが居る」とか「文字化けしている」とか。
UPDATEした際に、$_POST["id"]の値が空になっていたのが原因でした。
前のページからデータを引っ張ってきているものの、同ページ(ファイル)で
idに値を投げていなので当然ですよね・・・。
ありがとうございました。参考になりました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- PostgreSQL 画像とカテゴリーを出力したいのですが、取得の条件を付ける方法がわかりません。 2 2022/05/01 18:03
- PHP PHP MySql ページング 2 2022/09/20 06:38
- Oracle SQL update方法 2 2022/06/22 14:07
- PHP php テーブルが作成できない 1 2022/11/17 23:41
- Access(アクセス) アクセス テーブルの空白を変数に置換するボタンが作りたい 4 2022/07/08 11:19
- MySQL php テーブルを作れない 2 2022/11/17 18:22
- PHP DBのハッシュ化したパスワードをpassword_verifyで戻し照合したのですが上手く行きません 2 2023/02/06 13:24
- PHP 重複を防ぐ記述について教えて下さい。 3 2023/04/03 14:35
- MySQL UPDATE my_items SET item_name '赤い,甘い,ケーキ' WHERE id 1 2023/01/03 09:52
- MySQL 共通点はあります。何が違うのでしょうか? 1 2023/01/27 05:22
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C# ListBoxのインデックスの値...
-
ORA-01858: 数値を指定する箇所...
-
C#でラジオボタンとコンボボッ...
-
Java配列でNullPointerExceptio...
-
getStringの値がNULLの時の処理
-
BOOL値を逆にしたい
-
配列にnullを代入すると、null...
-
eclipseでoracle接続時のエラー...
-
入力された文字列の制限
-
javaで質問です。 文字列2023/2...
-
大量のデータを読み込んで表示...
-
ループ処理の際、最後だけ","を...
-
Javaで改行などが出来ないのです。
-
動的配列が存在(要素が有る)か...
-
ダブルクォーテーションのrepla...
-
substring バイト単位でやりたい
-
Javaでの改行コード
-
System.err. printlnとSystem.o...
-
VBAで配列の計算
-
C言語でunsigned char配列を連...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ORA-01858: 数値を指定する箇所...
-
配列にnullを代入すると、null...
-
Java配列でNullPointerExceptio...
-
BOOL値を逆にしたい
-
getStringの値がNULLの時の処理
-
C# ListBoxのインデックスの値...
-
eclipseでoracle接続時のエラー...
-
例外でBeanUtils.populateが、...
-
jsp/Servletの動的に増えるフォ...
-
Stringを返す getText()メソッ...
-
gas カレンダー祭日設定でエラー
-
JSPでの画面表示の方法
-
空欄のテキストフィールドの判...
-
C#でラジオボタンとコンボボッ...
-
JSPで複数のSQL実行につ...
-
逆コンパイルの見方について(...
-
Safari ダウンロード時に日本語...
-
java DAO 日付指定フォーマット...
-
oracle10g java jdbc 大量inser...
-
MySQLのテーブル名を変数に置い...
おすすめ情報