我有以下代码:
/** @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')
打开$打开时,结果为'1'
,'0'
(请参阅单引号)。
很遗憾,此输出会导致open = false
的新记录('1'
未正确插入true
)
如果我使用$db->boolean($open)
作为选项,一切正常。
但我认为,$db->value()
也应该做同样的工作?
答案 0 :(得分:3)
查看内部使用DboSource::value()
的时间和方式,这是预期的行为。如果它不能做它所做的事情,那么Model::save()
操作就无法正确准备值。
DboSource::value()
在内部将“booleanized”值(DboSource::boolean($value, true)
已添加引号)传递给PDO::quote()
,无论如何都会引用该值,即{{1 }},0
,1
,'0'
,'1'
或true
,它将始终返回引用值,即false
, '0'
甚至是'1'
(''
,等于false
)。
您的代码存在的问题是,传递给0
的第二个参数的值最终会传递给PDOStatement::execute()
( .../DboSource.php#L458 ),所有值都作为字符串并相应地转义它们,因此最终在您的查询中,Model::query()
将最终为'1'
,因此会出现问题。
TL; DR
这似乎是预期的行为,它的记录很差。因此,当使用'\'1\''
的第二个参数时,如果需要清理值(即转换为整数,布尔值,字符串等),但不要转义它们,只有在手动将它们插入实际查询字符串时才转义它们(应该尽可能避免)!