Laravel中如何按复合条件筛选关联数据?
关联字段联合筛选失效问题
问题背景
现有代码仅能通过Task的title字段搜索数据,company_id的筛选无法生效。模型结构:
- Category:id、name
- Task:id、title、category_id、company_id
- Company:id、name
现有Blade视图代码
<form action="/admin/manage" method="get"> <!-- 按Task标题搜索 --> <input name="search_name" value="{{ request('search_name') }}"> <!-- 按公司筛选 --> <select name="company_id"> <option value="" {{ request('company_id') == '' ? 'selected' : '' }}>Select All</option> @foreach($companies as $company) <option value="{{ $company->id }}" {{ request('company_id') == $company->id ? 'selected' : '' }}>{{ $company->name }}</option> @endforeach </select> <button type="submit">筛选</button> </form>
现有控制器代码
if($request->search_name || $request->company_id){ $categories = Category::with(['tasks' => fn($query) => $query->where('title', 'like', '%' . $request->search_name . '%')]) ->whereHas('tasks', fn ($query) => $query->where('title', 'like', '%' . $request->search_name . '%') )->get(); } else{ $categories = Category::with('tasks')->get(); }
解决方案
核心是在关联查询的闭包里同时处理两个筛选条件,且通过判断参数有效性避免空值干扰。
修正后的控制器代码
// 初始化查询构造器 $categoriesQuery = Category::query(); // 处理标题搜索:参数存在且非空时添加筛选 if ($request->filled('search_name')) { $searchTerm = '%' . $request->search_name . '%'; $categoriesQuery->whereHas('tasks', function ($query) use ($searchTerm) { $query->where('title', 'like', $searchTerm); }); } // 处理公司筛选:参数存在且非空时添加筛选 if ($request->filled('company_id')) { $categoriesQuery->whereHas('tasks', function ($query) use ($request) { $query->where('company_id', $request->company_id); }); } // 关联加载符合条件的tasks,同步应用筛选规则 $categories = $categoriesQuery->with(['tasks' => function ($query) use ($request) { if ($request->filled('search_name')) { $searchTerm = '%' . $request->search_name . '%'; $query->where('title', 'like', $searchTerm); } if ($request->filled('company_id')) { $query->where('company_id', $request->company_id); } }])->get();
代码说明
- 使用
filled()方法判断参数是否存在且非空,避免空字符串或null导致的错误筛选 - 拆分两个筛选条件的逻辑,支持单独筛选或联合筛选两种场景
with()关联查询同步应用筛选规则,确保返回的tasks数据与最终筛选结果一致- 模块化的逻辑结构,后续新增筛选条件时扩展更便捷
内容的提问来源于stack exchange,提问作者Muhammad Trian Syahputra
相关产品推荐
相关产品推荐

