【问题标题】:Query builder when() method producing wrongly conditioned query查询生成器 when() 方法产生条件错误的查询
【发布时间】:2021-12-13 17:43:47
【问题描述】:

我发布了我认为是 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);
});

从逻辑上讲,我认为它应该生成一个查询,该查询返回具有正确用户和正确描述的所有行,但无论描述如何,我都会获得该用户的所有行。

上面的代码产生了这个 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() 函数不应该在返回的结果周围加上括号以不影响查询的其他部分吗?它不是一个错误吗?

【问题讨论】:

    标签: laravel laravel-8 laravel-query-builder


    【解决方案1】:

    我不认为这是一个错误。这不是被破坏的预期行为。这将是添加到框架中的一项新功能。您可以访问 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);
           });
    

    【讨论】:

    • 好的。看完你说的,我意识到我错了。当然 when() 不应该影响查询。但有一件事是,这在文档中可能会更清楚。但我现在停止抱怨:-)
    猜你喜欢
    • 1970-01-01
    • 2021-09-07
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    • 2018-08-03
    • 2020-10-24
    • 2013-01-25
    • 1970-01-01
    相关资源
    最近更新 更多