为什么 PDO 将我的 bool(false) 参数转换为 string('')?

Cod*_*key 5 php mysql pdo mariadb

我在安装新的 MariaDB 10.5.8 时遇到问题。 STRICT_TRANS_TABLES已设置,当我尝试使用$sql

'INSERT INTO test (flag) VALUES (?)'
Run Code Online (Sandbox Code Playgroud)

(其中flag定义为tinyint(1)),var_dump($params)显示为:

array(1) {
  [0]=>
  bool(false)
}
Run Code Online (Sandbox Code Playgroud)

我收到这条消息:

Incorrect integer value: '' for column `mydb`.`test`.`flag` at row 1
Run Code Online (Sandbox Code Playgroud)

相反,如果我这样做:

'INSERT INTO test (flag) VALUES (false)'
Run Code Online (Sandbox Code Playgroud)

没有参数,它按预期工作。

这是我连接到数据库的方式:

$this->PDO = new PDO('mysql:host=' . DB_SERVER . ';dbname=' . DB_NAME . ';charset=utf8mb4', DB_USER, DB_PASSWORD, [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
    PDO::ATTR_STRINGIFY_FETCHES  => false,
]);

$this->PDO->query("SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'");
Run Code Online (Sandbox Code Playgroud)

这就是我将查询/参数发送到 MariaDB 的方式:

$stmt = self::$_instance->PDO->prepare($sql);
$stmt->execute($params);
Run Code Online (Sandbox Code Playgroud)

如果我尝试插入true而不是false,则一切正常。 true正在转换为1沿线的某个地方,并转换false''. 我究竟做错了什么?

Dur*_*oth 7

所有值都被视为PDO::PARAM_STR

https://www.php.net/manual/en/pdostatement.execute.php

execute()方法不允许您指定变量的类型。它总是转换为一个字符串,这就是为什么你会得到奇怪的结果:

php > var_dump((string) true);
string(1) "1"

php > var_dump((string) false);
string(0) ""
Run Code Online (Sandbox Code Playgroud)

您可以使用PDOStatement::bindValue()来指定值的类型:

$statement->bindValue('some_bool', true, PDO::PARAM_INT);
Run Code Online (Sandbox Code Playgroud)

注意,MySQL缺乏一个“真”布尔型,这就是为什么我建议PDO::PARAM_INTPDO::PARAM_BOOL


You*_*nse 6

一个更简单的解决方案是预先将布尔值转换为 int

$stmt = $PDO->prepare('INSERT INTO test (flag) VALUES (?)');
$stmt->execute([(int)$flag]);
Run Code Online (Sandbox Code Playgroud)

  • @Duroth我认为这是关于完整的转换链,PHP转换为int,然后PDO转换为字符串,最后mysql转换为int (2认同)