如何正确分组 Laravel Query Builder 中的 where 子句

Posted

技术标签:

【中文标题】如何正确分组 Laravel Query Builder 中的 where 子句【英文标题】:How to group where clauses in Laravel Query Builder correctly 【发布时间】:2021-03-17 23:22:30 【问题描述】:

我正在使用下面的 search() 函数运行以下查询 - 问题是我需要对 where 子句进行分组 - 我做错了什么?

select `standings`.*, `users`.`name` as `user` from `standings` 
left join `users` on `standings`.`user_id` = `users`.`id` 
where `users`.`name` like '%bob%' or `users`.`email` like '%bob%' 
and `standings`.`tenant_id` = '1'

在我的排名模型中,我有以下 search() 执行 WHERE 子句

public static function search($query)

  return empty($query) ? static::query()
         : static::where('users.name', 'like', '%'.$query.'%')
         ->orWhere('users.email', 'like', '%'.$query.'%');

public function render()

    $query = Standing::search($this->search)
        ->select('standings.*', 'users.name AS user')
        ->leftJoin('users', 'standings.user_id', '=', 'users.id')
        ->orderBy('points', 'desc')
        ->orderBy('goals_difference', 'desc')
        ->orderBy('goals_for', 'desc');
    if($this->super && $this->selectedTenant) 
        $query->where('standings.tenant_id', $this->selectedTenant);
    

    return view('livewire.show-standings', [
        'standings' => $query->paginate($this->perPage)
    ]);


查询有效,但是它没有在 users.name 和 users.email 字段上正确分组 WHERE 子句 - 我如何更改此 search() 函数,以便 WHERE 查询将它们分组为这样

where (`users`.`name` like '%bob%' or `users`.`email` like '%bob%')`

【问题讨论】:

你在寻找类似this的东西 【参考方案1】:

您需要将 where 子句分组到一个包装 where 子句中。试试这个

public static function search($query)

  return empty($query) 
    ? static::query()
    : static::where(function($query)
        $query->where('users.name', 'like', '%'.$query.'%')
            ->orWhere('users.email', 'like', '%'.$query.'%');
      );

谢谢,由于某种原因,即使看起来正确给了我以下错误 - 类 Illuminate\Database\Eloquent\Builder 的对象无法转换为字符串 NB 我正在将 Laravel 与 Livewire 一起使用(不确定这是否会有所不同)

$query->where('users.name', 'like', '%'.$query.'%')->orWhere('users.email', 'like', '%'.$query.'%'); 给出错误,因为在尝试比较 $query 时被视为字符串,因此出现错误

您可以将搜索定义为模型上的查询范围

//Assuming a relation Standing belongsTo User
//Query constraint to get all Standing records where
//related User record's name or email are like searchTerm
public function scopeSearch($query, string $searchTerm)

    return $query->whereHas('user', function($query) use($searchTerm)
        $query->where('name', 'like', "%$searchTerm)%")
            ->orWhere('email', 'like', "%$searchTerm%");
    );

Laravel 文档:https://laravel.com/docs/8.x/eloquent#local-scopes

通过在Standing模型上定义上述搜索范围,您可以将渲染功能设置为

public function render()

    $query = Standing::with('user:id,name')
        ->search($this->search)
        ->orderBy('points', 'desc')
        ->orderBy('goals_difference', 'desc')
        ->orderBy('goals_for', 'desc');
    if($this->super && $this->selectedTenant) 
        $query->where('tenant_id', $this->selectedTenant);
    

    return view('livewire.show-standings', [
        'standings' => $query->paginate($this->perPage)
    ]);


【讨论】:

感谢,尽管看起来正确,但由于某种原因给了我以下错误 - Object of class Illuminate\Database\Eloquent\Builder could not be converted to string 注意我正在使用 Laravel 和 Livewire(不确定这是否会有所不同) 别忘了->get()->first() 我在原始帖子中添加了更多上下文,希望可能有用 @Zabs 已更新答案以包括查询范围和错误的可能原因 绝对传奇@Donkarnash 这成功了!!仍然让我对范围很感兴趣,但是您一遍又一遍地找到了解决方案,非常感谢!

以上是关于如何正确分组 Laravel Query Builder 中的 where 子句的主要内容,如果未能解决你的问题,请参考以下文章

Laravel参数分组(和/或位置)

从 laravel 中的多个表中正确输出分组数据

Laravel Spatie Query Builder:使用 Axios 使用 API 的正确方法

Laravel - 使用唯一的 JSON 响应结构不正确

Laravel中的数字范围交点搜索

如何使用 laravel 中的 query() 函数对两个日期之间的数据进行排序