【问题标题】:Can you remove a clause from the query builder?您可以从查询构建器中删除子句吗?
【发布时间】:2018-12-18 08:31:05
【问题描述】:

查看API for Builder 似乎查询的所有部分都保存在$joins, $wheres, $groups 等属性中。 我还看到这些属性是公开的。

我的用例是例如范围,比方说(纯虚构)

class User extends Model
{
    public function scopeIsSmart($query)
    {
        return $query->join('tests', 'users.id', '=', 'tests.user')
            ->where('tests.score', '>', 130);
    }

    public function scopeIsMathGuy($query)
    {
        return $query->join('tests', 'users.id', '=', 'tests.user')
           ->where('tests.type', '=', 'math');
    }    
}

如果我现在写

User::query()->isSmart()->isMathGuy()->get();

我加入同一个表 2 次会出错。什么是使连接数组独一无二的好方法? (没有重复的连接)

【问题讨论】:

    标签: laravel eloquent query-builder


    【解决方案1】:

    您可以检查现有的 JOIN:

    public function scopeIsMathGuy($query)
    {
        if (collect($query->getQuery()->joins)->where('table', 'tests')->isEmpty()) {
            $query->join('tests', 'users.id', '=', 'tests.user');
        }
        $query->where('tests.type', '=', 'math');
    }
    

    您还可以创建一个类似joinOnce() 的助手(请参阅此PR)。

    【讨论】:

    • 可惜 Taylor 拒绝了 PR。
    【解决方案2】:

    试试这个:

    $query = Test::query();
       if ($request['is_smart']) {
          $query->where('score', '>', 130);
       }
    
       if ($request['is_math']) {
          $query->where('type', 'math');
       }
    $result = $query->with('users')->all();
    $users = $result->get('users');
    

    【讨论】:

    • 问题是关系(with())不会改变User的结果集。这就是为什么我要求在查询生成器上而不是在关系上这样做
    • 是的,这对于我的示例来说是一个可能的解决方案。我做得太简单了。但是,如果我们有一个由 4 个表(3 个连接)组成的查询,每个表的范围都是这样,这仍然不起作用。非常感谢您,但是您的解决方案是尝试将具有最多where 子句的表更改为from
    猜你喜欢
    • 1970-01-01
    • 2014-05-28
    • 2023-03-13
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 2023-02-12
    • 1970-01-01
    • 2011-01-22
    相关资源
    最近更新 更多