[PHP PDO]PDOでMySQL操作時、boolean型のデータをInsertできなかった件

今回、PDOを使ってMySQLに対してboolean型の値を登録しようとした際に、何故かうまく出来なかったのです。
調べたところ、初見殺しなところもあったのでブログに残しておくことに。

MySQLでのbooleanの扱いについて

まず、MySQLではカラム作成時にboolean型を選択できますが、実際に作成されたカラムはtinyint(1)となります。これ最初はバグかと思いましたが仕様みたいです。0=false,1=trueでいい感じに保存してくれます。
ただ今回PDOでうまく保存できなかったのはこれが原因ではありませんでした。

名前無しプレースホルダの仕様

まずうまくいかなかった時のコードについて。プレースホルダは名前なし(?を置き換えるやつ)。

$pdostatement->execute($params);

こんな感じで、SQL分には?をセットしておき、対応する値を配列で渡すというシンプルな構造。しかし、これだとboolean型の値を配列内にいれても、プレースホルダにはどうも空文字が渡されてしまう様子。そこでPDOStatementのbindParam()メソッドを使うことにしました。

    $count = 1;
    foreach($params as $paramTemp => &$param){
      if(is_bool($param))
        $pdoStatement->bindParam($count,$param,PDO::PARAM_BOOL);
      else
        $pdoStatement->bindParam($count,$param);
      $count++;
    }
    $result = $pdoStatement->execute();

このような感じで、まずパラメータ配列をforeachで回して、それぞれbindParamに明示的にセットするように変更しました。この際に、もし値がboolean型なら、PDO::PARAM_BOOLパラメータをセットするようにしています。こうすることでMySQLにも意図した値(true or false)が飛びます。

ここで注意しないといけないのが、bindParamは実行時に判定を行うということです。なので、foreachで毎回リセットされる変数を渡してしまうと意図しない動作になってしまうのです。

そこで、$paramTemp => &$paramとして参照渡しを行うことでそれぞれの値をbindParam時に読み取るようにしています。
これでうまく名前無しプレースホルダでもbooleanを渡すことができるようになりました。