简体   繁体   English

如何在CakePHP中手动转义mySQL数据库插入的布尔值?

[英]How to manually escape a boolean value for a mySQL Database insert in CakePHP?

i'm having the following code: 我有以下代码:

  /** @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 is a boolean value, the 'open' -column is defined as tinyint(1) . $open是一个布尔值, 'open' -column定义为tinyint(1) When wrapping $open with $db->value($open, 'boolean') the result is '1' , '0' (see the single quotes). 当用$db->value($open, 'boolean')包装$ open时,结果为'1''0' (请参见单引号)。

Unfortunately this output leads to a new record with open = false (as '1' is not properly inserted as true ) 不幸的是,此输出导致open = false的新记录(因为未正确将true插入'1'

If I use $db->boolean($open) as option, everything's working correctly. 如果我使用$db->boolean($open)作为选项,则一切正常。

But I think, $db->value() should do the same job as well? 但是我认为$db->value()应该做同样的工作吗?

Looking at when and how DboSource::value() is being used internally, this is the expected behavior. 查看何时以及如何在内部使用DboSource::value() ,这是预期的行为。 If it wouldn't do what it does, then values wouldn't get prepared properly for Model::save() operations. 如果它不做它所做的事情,那么就不会为Model::save()操作正确准备值。

DboSource::value() internally passes the "booleanized" value ( DboSource::boolean($value, true) this already adds quotes) to PDO::quote() , where the value is going to be quoted anyways no matter what, ie 0 , 1 , '0' , '1' , true , or false , it will always return a quoted value, that is '0' , '1' or even '' (for false , which is equal to 0 ). DboSource::value()内部将“ booleanized”值( DboSource::boolean($value, true)已将引号引起来)传递给PDO::quote() ,无论如何该值都将被引用,即01'0''1'truefalse ,这将始终返回引述的值,即'0''1'或甚至'' (为false ,这是等于0 )。

The problem with your code is, that values passed to the second argument of Model::query() are finally being passed to PDOStatement::execute() ( .../DboSource.php#L458 ), which treats all values as strings and escapes them accordingly, so finally in your query a '1' will end up as '\\'1\\'' , hence the problems. 您的代码的问题是,传递给Model::query()的第二个参数的值最终将传递给PDOStatement::execute()... / DboSource.php#L458 ),它将所有值视为字符串并相应地对其进行转义,因此最终在您的查询中, '1'将以'\\'1\\''结尾,因此出现了问题。

TL;DR TL; DR

This seems to be the expected behavior, it's just poorly documented. 这似乎是预期的行为,但文献记录很少。 So when using the second argument of Model::query() , sanitize the values if necessary (ie cast to integers, booleans, strings, etc), but do not escape them, escape them only when you manually insert them in the actual query string ( which should however be avoided whenever possible )! 因此,当使用Model::query()的第二个参数时,如有必要,对值进行清理(即,转换为整数,布尔值,字符串等),但不要对其进行转义,仅当您在实际查询中手动插入它们时才对它们进行转义字符串( 但是应尽可能避免使用 )!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM