どうも、コウイチです。
今回は、PHPでPDOを使用して、テーブルからint型の値を取り出してくるサンプルを見てみます。
これが、なかなか挙動が変だったのです。
次のコードを見てください。
サンプルコード
<?php // DB接続 $dsn = 'mysql:dbname=programming_blog;host=localhost'; $dbh = new PDO($dsn, 'root', 'pass'); $dbh->query('SET NAMES utf8'); // SQL準備 $sql = <<< SQL SELECT suuji FROM pdo_string; SQL; $stmt = $dbh->prepare($sql); // SQL実行 $stmt->execute(); $rec = $stmt->fetch(PDO::FETCH_ASSOC); if($rec['suuji'] === 3){ print $rec['suuji'] . 'は3です。'; }else{ print $rec['suuji'] . 'は3ではありません。'; } ?>
pdo_stringテーブルのsuujiというカラム(int型)に、3という数値がひとつだけ入っています。
この3をPDOで取り出しているのですが
実行結果:3は3ではありません。
という結果に。
いや明らかに3だろうがあwww
と、格闘しておりました。
どうやらPDOでテーブルから取り出した値は、全部文字列になるようですね。
だから 文字列 === 数値 の比較でfalseになるわけです。
この場合ですが、3を文字列として囲み、
if($rec[‘suuji’] === ‘3’){
とすれば正常に判定できます。
PDOのプリペアドステートメントエミュレートモードが原因らしい
それでは、何が原因なんでしょうか?
なんでPHPはMySQLからのリザルトがint型のはずなのにstring型になってしまうん?
こちらのサイトによると、PDOはデフォルトでプリペアドステートメントエミュレートモードになっているらしく、それが原因でこういった現象が起こるとのこと。
ただし、僕はこの挙動が分かってPHP側で対策してしまったので、深くは調査していません。
興味があれば調べてみてください。
ちなみに、バインドパラメータについても、文字列として扱われるようです。
PHP: PDOStatement::execute – Manual
実行される SQL 文の中のバインドパラメータと同数の要素からなる、 値の配列。すべての値は PDO::PARAM_STR として扱われます。
こちらも注意が必要ですね。
まとめ
デフォルトでこうなっている可能性が高いのに、意外とあまり騒がれていないものなんですね。
でも思わぬバグに繋がりかねません。頭の隅に入れておきましょう。
ではまた。
コメント