Cakephp 3.0 - 案例语句的查询生成器
Cakephp 3.0 - Query builder for case statements
我按照蛋糕的食谱php 3 创建了一个case语句
http://book.cakephp.org/3.0/en/orm/query-builder.html#case-statements
但结果 sql 查询与预期不符。语句的 'Else' 部分缺失
这是我的代码:
$query = $this->Attendees->find()->contain(['Users']);
$lastModifedCase = $query->newExpr()->addCase($query->newExpr()->add(['Attendees.modified <' => 'Users.modified']), [ 'Users.modified', 'Attendees.modified'], 'datetime');
$query->select(['Attendees.id', 'lastModified' => $lastModifedCase, 'Users.firstName', 'Users.lastName']);
die(var_dump($query->__debugInfo()));
在debugInfo中,这是我能看到的sql:
array(13) {
["sql"]=>
string(265) "SELECT Attendees.id AS `Attendees__id`, (CASE WHEN Attendees.modified < :c0 THEN :c1 END) AS `lastModified`, Users.firstName AS `Users__firstName`, Users.lastName AS `Users__lastName` FROM attendees Attendees INNER JOIN users Users ON Users.id = (Attendees.user_id)"
["params"]=>
array(2) {
[":c0"]=>
array(3) {
["value"]=>
string(14) "Users.modified"
["type"]=>
string(8) "datetime"
["placeholder"]=>
string(2) "c0"
}
[":c1"]=>
array(3) {
["value"]=>
string(14) "Users.modified"
["type"]=>
string(8) "datetime"
["placeholder"]=>
string(2) "c1"
}
}
["defaultTypes"]=>
array(8) {
["Attendees.id"]=>
string(7) "integer"
["id"]=>
string(7) "integer"
["Attendees.user_id"]=>
string(7) "integer"
["user_id"]=>
string(7) "integer"
["Attendees.created"]=>
string(8) "datetime"
["created"]=>
string(8) "datetime"
["Attendees.modified"]=>
string(8) "datetime"
["modified"]=>
string(8) "datetime"
}
"funny" 是食谱中的示例包含错误(变量 $unpublishedCase 应该是 $notPublishedCase)并且也没有给我预期的结果。这是它的 debugInfo(ps:我只是用我的与会者 table 替换了“$this->article”来测试这个例子)
array(13) {
["sql"]=>
string(190) "SELECT (SUM(CASE WHEN published = :c0 THEN :c1 END)) AS `number_published`, (SUM(CASE WHEN published = :c2 THEN :c3 END)) AS `number_unpublished` FROM attendees Attendees GROUP BY published "
["params"]=>
array(4) {
[":c0"]=>
array(3) {
["value"]=>
string(1) "Y"
["type"]=>
NULL
["placeholder"]=>
string(2) "c0"
}
[":c1"]=>
array(3) {
["value"]=>
int(1)
["type"]=>
string(7) "integer"
["placeholder"]=>
string(2) "c1"
}
[":c2"]=>
array(3) {
["value"]=>
string(1) "N"
["type"]=>
NULL
["placeholder"]=>
string(2) "c2"
}
[":c3"]=>
array(3) {
["value"]=>
int(1)
["type"]=>
string(7) "integer"
["placeholder"]=>
string(2) "c3"
}
}
["defaultTypes"]=>
array(8) {
["Attendees.id"]=>
string(7) "integer"
["id"]=>
string(7) "integer"
["Attendees.user_id"]=>
string(7) "integer"
["user_id"]=>
string(7) "integer"
["Attendees.created"]=>
string(8) "datetime"
["created"]=>
string(8) "datetime"
["Attendees.modified"]=>
string(8) "datetime"
["modified"]=>
string(8) "datetime"
}
当我深入蛋糕php代码时,我认为我的问题来自Cake\Database\Expression\CaseExpression的构造函数:
public function __construct($conditions = [], $values = [], $types = [])
{
if (!empty($conditions)) {
$this->add($conditions, $values, $types);
}
if (is_array($conditions) && is_array($values) && count($values) > count($conditions)) {
end($values);
$key = key($values);
$this->elseValue($values[$key], isset($types[$key]) ? $types[$key] : null);
}
}
$conditions不被认为是一个数组,所以没有设置else值。
cakephp的版本是3.0.1
php的版本是5.4.34
大家怎么看?我做错了什么还是错误?
在此先感谢您的指教
当您使用数组语法生成条件时,您需要记住数组的值 par 将始终被视为参数而不是原始字符串:
['field_name >' => 'this is just a value, not a raw string']
原因是它可以防止 SQL 注入攻击。要解决您的问题,请执行以下操作:
['Attendees.modified < Users.modified']
而不是这个:
['Attendees.modified <' => 'Users.modified']
晚安后我发现了我的错误,我与你分享......希望有一天它能帮助别人。
语法不正确,$condition 肯定不是数组。
$lastModifedCase = $query->newExpr()->addCase(
$query->newExpr()->add([
'Attendees.modified <' => 'Users.modified'
]),
['Users.modified', 'Attendees.modified'],
'datetime'
);
正确的语法是:
$lastModifedCase = $query->newExpr()->addCase(
[$query->newExpr()->add('Attendees.modified < Users.modified')],
[ 'Users.modified', 'Attendees.modified'],
['datetime','datetime']
);
我也:
- 根据 José Lorenzo 的回答调整了条件
- 指定了每个值的类型('datetime' 的数组代替
一个字符串)。否则,我得到一个 "wrong type" 错误。
我按照蛋糕的食谱php 3 创建了一个case语句 http://book.cakephp.org/3.0/en/orm/query-builder.html#case-statements
但结果 sql 查询与预期不符。语句的 'Else' 部分缺失
这是我的代码:
$query = $this->Attendees->find()->contain(['Users']);
$lastModifedCase = $query->newExpr()->addCase($query->newExpr()->add(['Attendees.modified <' => 'Users.modified']), [ 'Users.modified', 'Attendees.modified'], 'datetime');
$query->select(['Attendees.id', 'lastModified' => $lastModifedCase, 'Users.firstName', 'Users.lastName']);
die(var_dump($query->__debugInfo()));
在debugInfo中,这是我能看到的sql:
array(13) {
["sql"]=>
string(265) "SELECT Attendees.id AS `Attendees__id`, (CASE WHEN Attendees.modified < :c0 THEN :c1 END) AS `lastModified`, Users.firstName AS `Users__firstName`, Users.lastName AS `Users__lastName` FROM attendees Attendees INNER JOIN users Users ON Users.id = (Attendees.user_id)"
["params"]=>
array(2) {
[":c0"]=>
array(3) {
["value"]=>
string(14) "Users.modified"
["type"]=>
string(8) "datetime"
["placeholder"]=>
string(2) "c0"
}
[":c1"]=>
array(3) {
["value"]=>
string(14) "Users.modified"
["type"]=>
string(8) "datetime"
["placeholder"]=>
string(2) "c1"
}
}
["defaultTypes"]=>
array(8) {
["Attendees.id"]=>
string(7) "integer"
["id"]=>
string(7) "integer"
["Attendees.user_id"]=>
string(7) "integer"
["user_id"]=>
string(7) "integer"
["Attendees.created"]=>
string(8) "datetime"
["created"]=>
string(8) "datetime"
["Attendees.modified"]=>
string(8) "datetime"
["modified"]=>
string(8) "datetime"
}
"funny" 是食谱中的示例包含错误(变量 $unpublishedCase 应该是 $notPublishedCase)并且也没有给我预期的结果。这是它的 debugInfo(ps:我只是用我的与会者 table 替换了“$this->article”来测试这个例子)
array(13) {
["sql"]=>
string(190) "SELECT (SUM(CASE WHEN published = :c0 THEN :c1 END)) AS `number_published`, (SUM(CASE WHEN published = :c2 THEN :c3 END)) AS `number_unpublished` FROM attendees Attendees GROUP BY published "
["params"]=>
array(4) {
[":c0"]=>
array(3) {
["value"]=>
string(1) "Y"
["type"]=>
NULL
["placeholder"]=>
string(2) "c0"
}
[":c1"]=>
array(3) {
["value"]=>
int(1)
["type"]=>
string(7) "integer"
["placeholder"]=>
string(2) "c1"
}
[":c2"]=>
array(3) {
["value"]=>
string(1) "N"
["type"]=>
NULL
["placeholder"]=>
string(2) "c2"
}
[":c3"]=>
array(3) {
["value"]=>
int(1)
["type"]=>
string(7) "integer"
["placeholder"]=>
string(2) "c3"
}
}
["defaultTypes"]=>
array(8) {
["Attendees.id"]=>
string(7) "integer"
["id"]=>
string(7) "integer"
["Attendees.user_id"]=>
string(7) "integer"
["user_id"]=>
string(7) "integer"
["Attendees.created"]=>
string(8) "datetime"
["created"]=>
string(8) "datetime"
["Attendees.modified"]=>
string(8) "datetime"
["modified"]=>
string(8) "datetime"
}
当我深入蛋糕php代码时,我认为我的问题来自Cake\Database\Expression\CaseExpression的构造函数:
public function __construct($conditions = [], $values = [], $types = [])
{
if (!empty($conditions)) {
$this->add($conditions, $values, $types);
}
if (is_array($conditions) && is_array($values) && count($values) > count($conditions)) {
end($values);
$key = key($values);
$this->elseValue($values[$key], isset($types[$key]) ? $types[$key] : null);
}
}
$conditions不被认为是一个数组,所以没有设置else值。
cakephp的版本是3.0.1
php的版本是5.4.34
大家怎么看?我做错了什么还是错误?
在此先感谢您的指教
当您使用数组语法生成条件时,您需要记住数组的值 par 将始终被视为参数而不是原始字符串:
['field_name >' => 'this is just a value, not a raw string']
原因是它可以防止 SQL 注入攻击。要解决您的问题,请执行以下操作:
['Attendees.modified < Users.modified']
而不是这个:
['Attendees.modified <' => 'Users.modified']
晚安后我发现了我的错误,我与你分享......希望有一天它能帮助别人。
语法不正确,$condition 肯定不是数组。
$lastModifedCase = $query->newExpr()->addCase(
$query->newExpr()->add([
'Attendees.modified <' => 'Users.modified'
]),
['Users.modified', 'Attendees.modified'],
'datetime'
);
正确的语法是:
$lastModifedCase = $query->newExpr()->addCase(
[$query->newExpr()->add('Attendees.modified < Users.modified')],
[ 'Users.modified', 'Attendees.modified'],
['datetime','datetime']
);
我也:
- 根据 José Lorenzo 的回答调整了条件
- 指定了每个值的类型('datetime' 的数组代替 一个字符串)。否则,我得到一个 "wrong type" 错误。