bindParamとbindValue
pdoを使ってプリペアードステートメントから各値をバインドするための関数が2つ用意されている。bindParamとbindValueだ。bindValueはコマンドが発行される都度SQL文に値がセットされるのに対し、bindParamは参照で値が渡され、execute実行時に初めて値に変換される。とりあえずマニュアルを読んで理解していたつもりだったのだが、やっぱり「つもり」だった。
$sql=’INSERT INTO table VALUES (?,?)';
上記のSQL文をプリペアードステートメントとしてセットし値をバインドしていくわけだが、こんなことをしてしていた。
$values=array(1=>3,2=>5);
foreach($values as $name => $value){
$preparedStatementObj->bindParam($name,$value);
}
$preparedStatementObj->execute();
こうすると、tableには(3,5)というデータが格納されてほしいのに、(5,5)というデータが入ってしまう。最初はまったく意味がわからなくて30分くらい悩んでしまった。そこでマニュアル読み直し。「参照渡し」「execute実行時に初めて・・・」。あ、そうか。値を渡すときに使う変数がいつも$valueだから、execute実行時には最後の$valueの値に置き換えられてしまっていたのか。
問題を解決する方法はbindValueを使うか、値をセットする都度異なる変数名を使用するか、のいずれか。どちらで試しても大丈夫だった。まさしく生兵法は怪我の基だった。