かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

PHP PDO bindParam()と日付型(DATE, DATETIME)とBOOL型にハマる

PHPのPDOを使ってDBにデータを挿入しようとした際にハマりました。

bindParam()に直接値を書くをエラーになる。

データが無ければnullを入れようと思い下記の様なコードを書いていました。

<?php
$stmt = $pdo->("INSERT INTO {$TABLE} (data) VALUES (:data)");

if(!empty($data)) {
  $stmt->bindParam(':data', $data, PDO::PARAM_STR);
} else {
  $stmt->bindParam(':data', null, PDO::PARAM_NULL);
}
$stmt->execute();

データが無い時次のようなエラーになりました。。。

Fatal error: Cannot pass parameter 2 by reference

どうやらbindParam()は第2引数に直接値を与えることができないっぽい!
一度変数に入れてあげないとダメなようです。なので下記のように書き変えればOK

<?php
$stmt = $pdo->("INSERT INTO {$TABLE} (data) VALUES (:data)");

if(!empty($data)) {
  $stmt->bindParam(':data', $data, PDO::PARAM_STR);
} else {
  $null = null; // 一旦変数を作る
  $stmt->bindParam(':data', $null, PDO::PARAM_NULL);
}
$stmt->execute();

何だかビミョーです...
bindValue()を使えば直接値を渡しても問題ないようです。
bindValue() で書き換える。

<?php
$stmt = $pdo->("INSERT INTO {$TABLE} (data) VALUES (:data)");

if(!empty($data)) {
  $stmt->bindValue(':data', $data, PDO::PARAM_STR);
} else {
  $stmt->bindValue(':data', null, PDO::PARAM_NULL);
}
$stmt->execute();

bindParam()bindValue()の違いは

  • bindParam()は変数をバインドしexecute()が実行された時にバインドされた変数を参照する
  • bindValue()は値をバインドする

という事のようです。

bindParam()は変数をバインドした時にはexecute()する前に同じ変数の値を変えてしまうと予期しない値がDBに渡ってしまう可能性があったり、execute()時にINT型が文字列に変換されたりするので気をつけた方が良さそうと思いました。

日付型(DATE, DATETIME)が存在しない?

DBの型がDATE、DATETIMEになっているカラムに値を入れようとしました。

<?php
$stmt = $pdo->("INSERT INTO {$TABLE} (date, created_at) VALUES (:date, :created_at)");

$date = new Date('2014-01-18');
$stmt->bindValue(':date', $date->format('Y-m-d'), PDO::PARAM_DATE);

$created_at = new Date();
$stmt->bindValue(':date', $created_at->format('Y-m-d H:i:s'), PDO::PARAM_DATETIME);

$stmt->execute();

次のようなエラーが出ました。

Fatal error: Undefined class constant 'PARAM_DATE'

どうやらPDOにはPARAM_DATEPARAM_DATETIMEが無いっぽい。
仕方が無いので文字列PARAM_STRでデータを挿入することにしました。。。

<?php
$stmt = $pdo->("INSERT INTO {$TABLE} (date, created_at) VALUES (:date, :created_at)");

$date = new Date('2014-01-18');
$stmt->bindValue(':date', $date->format('Y-m-d'), PDO::PARAM_STR);

$created_at = new Date();
$stmt->bindValue(':date', $created_at->format('Y-m-d H:i:s'), PDO::PARAM_STR);

$stmt->execute();

BOOL型が上手くINSERTできない

DB作成時にis_bool BOOLEANで作成したカラムにPDO:: PARAM_BOOLでデータを入れようとしてハマりました。

<?php
$stmt = $pdo->("INSERT INTO {$TABLE} (is_bool) VALUES (:is_bool)");

// true
$is_bool = true;
$stmt->bindValue(':is_bool', $is_bool, PDO::PARAM_BOOL);
$stmt->execute(); // -> false

// false
$is_bool = false;
$stmt->bindValue(':is_bool', $is_bool, PDO::PARAM_BOOL);
$stmt->execute(); // -> false

BOOL型のカラムにtruefalseでデータを入れようとしたのですが、データの挿入に失敗しているようです...
もしかしてと思いDBを見に行くと、is_boolカラムの型がTINYINTになっていました。
MySQLでBOOL型で作成したカラムはTINYINTになるようです。
DBの型がBOOLEANでない。もしかしてコレが原因?と思いPARAM_INTにしてみたら上手く動作しました。

<?php
$stmt = $pdo->("INSERT INTO {$TABLE} (is_bool) VALUES (:is_bool)");

// true
$is_bool = true;
$stmt->bindValue(':is_bool', $is_bool, PDO::PARAM_INT);
$stmt->execute(); // -> true

// false
$is_bool = false;
$stmt->bindValue(':is_bool', $is_bool, PDO::PARAM_INT);
$stmt->execute(); // -> true

   

最近Node.jsやRubyばかり触っていてPHPを殆ど触ってなかったので色々とPHPの事を忘れてるは、色んな所にハマりまくるはで疲れきってしまいました。PHP...

本題とは関係がないのだけど、MarkdownにしたらQiitaのリンクを挿入した時に上手くタイトルが表示されないっぽい!↓ [http://qiita.com/dozen/items/e3c00a0a581378a4cc70:title]
わざわざ[タイトル](URL)で書きなおすのめんどくさいです。。。


参考にしました