変数を評価するタイミング
$statement = $database->prepare('INSERT INTO favorite_category (id_users, category_id) values(:id, :category_id)');
$id = 3;
$categoryID = 10;
$statement->bindParam(':id', $id);
$statement->bindParam(':category_id', $categoryID);
$statement->execute();
$statement->bindValue(':id', 3);
$statement->bindValue(':category_id', 10);
$statement->execute();
bindParam()は変数を入れないとエラーが出る。bindValue()は値を直接入れても、変数を入れてもOK。
bindParam()はexecute()された時点で変数を評価する。bindValue()はすぐに変数を評価。
$a = [
'id' => 2,
'user' => 'jack',
'sex' => 1,
'prefecture' => 24
];
$statement = $db->prepare('INSERT INTO users (id, name, sex, birthday, prefecture) VALUES (?, ?, ?, ?)');
$statement->bindParam(1, $a['id'], PDO::PARAM_STRING);
$statement->bindParam(1, $a['name'], PDO::PARAM_INT);
$statement->bindParam(2, $a['sex'], PDO::PARAM_INT);
$statement->bindParam(4, $a['prefecture'], PDO::PARAM_STRING);
$statement->execute();
bindParam()はその場では変数が評価されないので未定義の配列を指定してもエラーが出ないし、未定義のまま実行してもエラーは出ない。bindValue()だと未定義の配列を指定するとエラーが出る。
bindParam()の副作用(?)
$statement = $database->prepare(/** 省略 **/);
$id = 3;
$statement->bindParam(':id', $id, PDO::PARAM_INT);
var_dump($id); //=> int(3);
$statement->execute();
var_dump($id); //=> string(1) "3"
bindParam()
を使った場合にのみ発生する。execute()
を実行したあとにbindParam()
に渡した変数が文字列型になってしまう。strange_behavior.php
の場合だと, $id
が整数型から文字列型に変わっている. なので, クエリを実行した後に$id
を何かの処理で使用する場合, 思わぬ挙動をするおそれがある.
PDOにもそんな例があって, まさにstrange_behavior.php
のbindParam()
がそれにあたる. 第3引数にPDO::PARAM_INT
を指定すると, バインドする変数が整数型でない場合にエラーとなってしまう. 変数$id
を使って何度もクエリを実行する場合には, 結構厄介な問題になる気がする.