我有以下代码:
/** @var DboSource $db */
$db = $this->getDataSource();
var_dump($db->value($open, 'boolean'));
die;
$this->query(
'INSERT INTO foo(`client_id`, `open`, `modified`, `created`) VALUES(:clientId, :open, NOW(), NOW()) ON DUPLICATE KEY UPDATE modified = now();',
[
':clientId' => $db->value($clientId, 'integer'),
':open' => $db->value($open, 'boolean')
]
);
$open
是布尔值,'open'
列定义为 tinyint(1)
。当用$db->value($open, 'boolean')
包装$open时,结果是 '1'
、 '0'
(请参阅单引号(。
不幸的是,此输出会导致一条带有open = false
的新记录(因为'1'
未正确插入true
(
如果我使用$db->boolean($open)
作为选项,一切正常。
但我认为,$db->value()
也应该做同样的工作吗?
查看内部使用DboSource::value()
的时间和方式,这是预期的行为。如果它不执行它所做的事情,那么值就不会为Model::save()
操作正确准备。
DboSource::value()
内部将"布尔化"值(DboSource::boolean($value, true)
这已经加了引号(传递给PDO::quote()
,无论如何,该值都将被引用,即0
、1
、'0'
、'1'
、true
或false
,它将始终返回一个引号值,即'0'
、'1'
甚至''
(对于false
, 等于 0
(。
代码的问题在于,传递给Model::query()
第二个参数的值最终被传递给PDOStatement::execute()
(.../DboSource.php#L458(,它将所有值视为字符串并相应地转义它们,因此最终在您的查询中,'1'
将最终为 '''1'''
,因此存在问题。
博士
这似乎是预期的行为,只是记录不足。因此,当使用 Model::query()
的第二个参数时,如有必要,请清理值(即转换为整数、布尔值、字符串等(,但不要转义它们,仅当您手动将它们插入实际查询字符串时才对其进行转义(但是应尽可能避免(!