You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Eloquent如何结合查询作用域筛选公开文章并多字段模糊搜索?

Laravel Eloquent: 结合查询作用域实现公开内容的多字段模糊搜索

你的需求其实是Eloquent里很常见的场景,核心要避开的一个坑就是OR条件的逻辑分组——如果直接把published作用域和一堆orWhere链式调用,会导致逻辑变成「(published=open) OR (username匹配) OR ...」,这完全偏离了你「先筛选公开内容,再在其中做多字段搜索」的目标。

直接可用的解决方案

$search = $request->get('q');

$users = User::published() // 先过滤出公开状态的用户
    ->where(function ($query) use ($search) {
        // 把所有模糊匹配的OR条件打包在这个闭包里
        $query->where('username', 'like', "%{$search}%")
            ->orWhere('displayName', 'like', "%{$search}%")
            ->orWhere('email', 'like', "%{$search}%")
            ->orWhere('role', 'like', "%{$search}%")
            ->orWhere('department', 'like', "%{$search}%")
            ->orWhere('location', 'like', "%{$search}%")
            ->orWhere('directDialIn', 'like', "%{$search}%")
            ->orWhere('mobileNumber', 'like', "%{$search}%");
    })
    ->get();

为什么要这么写?

这里的关键是用闭包包裹所有orWhere条件:

  1. User::published()会先给查询加上WHERE published = 'open'的基础条件,对应你要的「仅公开内容」筛选。
  2. 闭包里的orWhere会被Eloquent自动用括号包裹起来,最终生成的SQL逻辑是:
    SELECT * FROM users 
    WHERE published = 'open' 
    AND (
        username LIKE '%搜索词%' 
        OR displayName LIKE '%搜索词%' 
        OR ...其他字段...
    )
    
    完美实现了「先筛选公开,再在其中做多字段模糊匹配」的逻辑。

从原生SQL到Eloquent的转换小技巧

如果你习惯了写原生SQL,转Eloquent的时候可以记住这几个对应规则:

  • 原生SQL里的WHERE 条件A AND (条件B OR 条件C) → Eloquent里对应where(条件A)->where(function($q) { $q->orWhere(条件B)->orWhere(条件C); })
  • 查询作用域就是封装好的查询片段,直接链式调用即可,和普通的where、orderBy用法完全一致
  • 闭包要访问外部变量(比如这里的$search),必须用use()把变量传进去
  • 模糊匹配的%可以用PHP字符串插值"%{$search}%",比字符串拼接更简洁易读

进阶优化:封装搜索逻辑为作用域

如果以后需要在多个地方用到这个多字段搜索,还可以把它封装成另一个查询作用域,让代码更简洁:

// 在User模型里新增作用域
public function scopeSearch($query, $searchTerm)
{
    return $query->where(function ($q) use ($searchTerm) {
        $q->where('username', 'like', "%{$searchTerm}%")
          ->orWhere('displayName', 'like', "%{$searchTerm}%")
          ->orWhere('email', 'like', "%{$searchTerm}%")
          ->orWhere('role', 'like', "%{$searchTerm}%")
          ->orWhere('department', 'like', "%{$searchTerm}%")
          ->orWhere('location', 'like', "%{$searchTerm}%")
          ->orWhere('directDialIn', 'like', "%{$searchTerm}%")
          ->orWhere('mobileNumber', 'like', "%{$searchTerm}%");
    });
}

之后调用就会非常清爽:

$users = User::published()->search($request->get('q'))->get();

内容的提问来源于stack exchange,提问作者Jesse Luke Orange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:02:50