ヽ(`@A@´#)ノ ムキー!!
前提
久しぶりにフレームワークの入らないPHPを書きました。
$_POSTで受け取ったデータをDBに書き込むだけの簡単なお仕事です。
function insert($dto){
$sql = 'insert into '.TABLE.'('.implode(',',DTO::get_insert_key()).') values ('.implode(',',DTO::get_insert_holder()).')';
$stmt = $this->pdo->prepare($sql);
foreach(DTO::get_insert_holder() as $holder){
$key=substr($holder,1); // ※ここは単に:取り除いてるだけ
$val=$dto->get($key);
$b=$stmt->bindParam($holder ,$val);
}
$stmt->execute();
}
※DTO::get_insert_keyはDBのカラム名を配列で、get_insert_holderはカラム名それぞれコロンが付いた形の配列が返ってきます(何もかも外部化したい病気)。
……動かない。動かないというか、つめ込まれた変数がおかしい。
途中にアイキャッチャー挟んで全ての変数を追ってもおかしいところがないのに、execute時点ではどうもデータが変わってしまっている。
時間は全て0000-00-00 00:00:00だし、吐出されるはずのSQLをphpMyAdminで叩いてみても異常は見られない。
結論
SQLStatement::bindParamの第二引数は 参 照 渡 し でした。
つまり、foreachループ内で$valの中身が変わるとそちらでSQLを作成してしまう。
私の場合末尾に入っていた文字列で全ての変数をバインド、DB側でエラーを起こして初期値が入ってしまう、ということでした。
リファレンス何回も見てたのになぜ気がつけなかったのか、こんなことで半日を潰しました。
解決策
SQLStatement::bindValueを使いましょう。
※ループ回さないできっちり変数名を指定するのが一番無難です。