(2020/3/27 追記)徳丸さんが記事書かれたので、リンクしときます!
PHP 7.2以降におけるPDO::PARAM_INTの仕様変更
さすが、検証の方法が、私のよりちゃんとしてますね^^;
float に関しての言及がないので、一応、以下は役に立つはず!
以下、元記事
あの何もしないことで有名な PDO::PARAM_INT の仕様がいつのまにか変わっていました。
が、解説記事が見当たらなかったので、検証とともに記事にしときます。
多分、アップグレードガイドにも載ってない秘密の情報ですw1
何もしない PDO::PARAM_INT とは?
PDO 使用している人には結構有名な話ですが、こいつ、ほとんど働きませんでしたw
参考記事:PDOでの数値列の扱いにはワナがいっぱい(2)
PDO::PARAM_INTはboolをintに変換(他は何もしない)
つまり、int へキャストされることを期待して
$stmt->bindValue(':test', 1.1, PDO::PARAM_INT);
なんてぶっこんでも、普通に1.1
が投入されます
サボりすぎだろw
#何が変わったのか?
プリペアドステートメントのエミュレーションが ON な時、ちゃんと働くようになりました!
正しく、int へキャストされます
本件は以下の変更で対応されたようです。
Emulated statements let value dictate parameter type
ただし、エミュレーションが OFF だと、まだサボりやがりますw
検証
以下のサンプルをいくつかのバージョンで動かしてみました。
<?php
try {
$pdo = new PDO(
'mysql:dbname=hoge;host=localhost;charset=utf8',
'',
'',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
// PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_EMULATE_PREPARES => true,
]
);
$stmt = $pdo->prepare('INSERT INTO test (php_v,test) VALUES (:php,:test)');
$stmt->bindValue(':php', phpversion(), PDO::PARAM_STR);
$stmt->bindValue(':test', 1.1, PDO::PARAM_INT);
$stmt->execute();
} catch (PDOException $e) {
exit($e->getMessage());
}
php のバージョン | エミュレーション | 値 |
---|---|---|
7.1.33 | OFF | 1.1 |
7.1.33 | ON | 1.1 |
7.2.26 | OFF | 1.1 |
7.2.26 | ON | 1 |
7.3.13 | OFF | 1.1 |
7.3.13 | ON | 1 |
7.4.1 | OFF | 1.1 |
7.4.1 | ON | 1 |
#影響
いくつかのトラブルを見ると、float にデータを突っ込む時にPDO::PARAM_STR
を使うのを気持ち悪がって、PDO::PARAM_INT
を採用したケースで被害が出ているようです。
まぁ、2択で INT を選ぶ気持ちはわかる!
これ、結構でかい問題になると思うので、バージョンアップ対応時には注意してください。
-
Binding value as PDO::PARAM_INT has different behaviour in PHP 7.2 で、なぜかアップグレードガイドに載せることがスルーされてます ↩