Laravel Eloquent实现匹配项目或关联条目任意标题并返回结果的方法
Laravel 关联模型多字段搜索实现方案
原代码问题分析
你原来的写法问题根源是混淆了with和whereHas的作用:
- 主查询只限定了
projects.title匹配搜索词,所以只要项目标题不匹配,哪怕关联的条目有符合条件的,主查询也不会返回该项目 with闭包仅用于过滤预加载的关联数据,不会对主查询的结果筛选产生任何影响,单独用预加载确实无法实现你的需求。
实现逻辑说明
你最终采用的orWhereHas思路是正确的,whereHas的作用就是检测关联模型是否存在符合条件的记录,会直接影响主模型的查询结果,刚好满足「只要项目标题匹配或者关联条目标题匹配就返回项目」的要求。
要完全匹配你的业务规则,还要调整预加载部分的逻辑,完整可运行代码如下:
$search = $this->search; $projects = Auth::user()->projects() // 主查询筛选:项目标题匹配 或者 存在匹配的关联条目 ->where(function($query) use ($search) { $query->where('title', 'LIKE', "%{$search}%") ->orWhereHas('items', function($q) use ($search) { $q->where('title', 'LIKE', "%{$search}%"); }); }) // 预加载条目和标签,按需过滤条目 ->with(['items' => function($q) use ($search) { // 如果项目本身标题已经匹配搜索词,返回所有条目;否则只返回匹配的条目 $q->where(function($q) use ($search) { $q->where('title', 'LIKE', "%{$search}%") ->orWhereRaw('exists (select 1 from projects where projects.id = items.project_id and projects.title like ?)', ["%{$search}%"]); })->with('tags'); }]) ->get();
逻辑验证
- 搜索词仅匹配项目标题:主查询筛选出该项目,预加载时
orWhereRaw条件生效,返回项目下所有条目及关联标签 - 搜索词仅匹配条目:主查询通过
orWhereHas筛选出条目的所属项目,预加载时仅返回匹配的条目及关联标签 - 搜索词同时匹配项目和条目:两种规则同时生效,返回项目和所有符合规则的条目
内容的提问来源于stack exchange,提问作者SeaBass
相关产品推荐
相关产品推荐

