查询生成器 when() 方法生成条件错误的查询
Query builder when() method producing wrongly conditioned query
我发布了一个我认为是 Laravel 错误 (https://github.com/laravel/framework/issues/39398) 的帖子,但它已被关闭,因为我不是 100% 确定它确实是一个错误。其他人可以告诉我这种行为是否有误吗?
我有如下一段代码:
$user=251;
$description='created';
Activity::when($user, function ($query, $user) {
return $query->where('causer_id', $user)
->orWhere(function($query) use ($user) {
$query->where('subject_id', $user)
->where('subject_type', "App\User");
});
})->when($description, function ($query, $description) {
return $query->where('description', $description);
});
从逻辑上讲,我认为它应该生成一个查询,该查询 return 所有具有正确用户和正确描述的行,但无论描述如何,我都会得到该用户的所有行。
上面的代码产生这个 sql 查询:
select * from activity_log where causer_id = '251' or (subject_id = '251' and subject_type = 'App\User') and description = 'created'
...而我认为它应该产生:
select * from activity_log where (causer_id = '251' or (subject_id = '251' and subject_type = 'App\User')) and (description = 'created')
简而言之:when() 函数不应该在其 returned 结果周围加上括号以不影响查询的其他部分吗?它不是一个错误吗?
我不认为这是一个错误。这不是破坏的预期行为。这将是一个要添加到框架中的新功能。您可以访问 Discord 服务器并尝试提出您的理由,或者简单地提交包含更改的 PR 并为其辩护,但这并不是“破坏”了现有功能。
when()
方法只是语法糖,因此您可以有条件地修改方法链中的查询,而不必分解为单独的 if
语句。以下代码是等效的:
$query = Activity::query();
if ($user) {
$query->where('causer_id', $user)
->orWhere(function($query) use ($user) {
$query->where('subject_id', $user)
->where('subject_type', "App\User");
});
}
if ($description) {
$query->where('description', $description);
}
如您在上面的代码中所见,不会期望任何有条件添加的子句都包含在括号中(除非在您的 orWhere()
调用中明确指定)。
您所期望的一个问题是 when()
方法可用于以任何方式修改查询,而不仅仅是添加额外的条件。因此,如果您在 when()
子句中添加 orderBy()
或 limit()
,您希望发生什么情况?
因此,when()
方法本身不会修改您的查询,但它会 运行 完全按照您的指示进行修改。因此,要执行您正在寻找的操作,您需要自己将查询包装在 when()
子句中:
Activity::when($user, function ($query, $user) {
return $query->where(function($query) use ($user) {
return $query->where('causer_id', $user)
->orWhere(function($query) use ($user) {
$query->where('subject_id', $user)
->where('subject_type', "App\User");
});
});
})
->when($description, function ($query, $description) {
return $query->where('description', $description);
});
我发布了一个我认为是 Laravel 错误 (https://github.com/laravel/framework/issues/39398) 的帖子,但它已被关闭,因为我不是 100% 确定它确实是一个错误。其他人可以告诉我这种行为是否有误吗?
我有如下一段代码:
$user=251;
$description='created';
Activity::when($user, function ($query, $user) {
return $query->where('causer_id', $user)
->orWhere(function($query) use ($user) {
$query->where('subject_id', $user)
->where('subject_type', "App\User");
});
})->when($description, function ($query, $description) {
return $query->where('description', $description);
});
从逻辑上讲,我认为它应该生成一个查询,该查询 return 所有具有正确用户和正确描述的行,但无论描述如何,我都会得到该用户的所有行。
上面的代码产生这个 sql 查询:
select * from activity_log where causer_id = '251' or (subject_id = '251' and subject_type = 'App\User') and description = 'created'
...而我认为它应该产生:
select * from activity_log where (causer_id = '251' or (subject_id = '251' and subject_type = 'App\User')) and (description = 'created')
简而言之:when() 函数不应该在其 returned 结果周围加上括号以不影响查询的其他部分吗?它不是一个错误吗?
我不认为这是一个错误。这不是破坏的预期行为。这将是一个要添加到框架中的新功能。您可以访问 Discord 服务器并尝试提出您的理由,或者简单地提交包含更改的 PR 并为其辩护,但这并不是“破坏”了现有功能。
when()
方法只是语法糖,因此您可以有条件地修改方法链中的查询,而不必分解为单独的 if
语句。以下代码是等效的:
$query = Activity::query();
if ($user) {
$query->where('causer_id', $user)
->orWhere(function($query) use ($user) {
$query->where('subject_id', $user)
->where('subject_type', "App\User");
});
}
if ($description) {
$query->where('description', $description);
}
如您在上面的代码中所见,不会期望任何有条件添加的子句都包含在括号中(除非在您的 orWhere()
调用中明确指定)。
您所期望的一个问题是 when()
方法可用于以任何方式修改查询,而不仅仅是添加额外的条件。因此,如果您在 when()
子句中添加 orderBy()
或 limit()
,您希望发生什么情况?
因此,when()
方法本身不会修改您的查询,但它会 运行 完全按照您的指示进行修改。因此,要执行您正在寻找的操作,您需要自己将查询包装在 when()
子句中:
Activity::when($user, function ($query, $user) {
return $query->where(function($query) use ($user) {
return $query->where('causer_id', $user)
->orWhere(function($query) use ($user) {
$query->where('subject_id', $user)
->where('subject_type', "App\User");
});
});
})
->when($description, function ($query, $description) {
return $query->where('description', $description);
});