Laravel严格模式下优化关联查询:替换with为load及精简写法
Laravel代码优化方案
优化后的代码
// 构建主模型查询条件,全程使用模型/关联名,避免直接写表名 $bunniesQuery = Bunny::query() ->when($request->carrotStatus, function ($query) use ($request) { $query->whereHas('carrots', fn($q) => $q->where('status', $request->carrotStatus)); }) ->when($request->multiSearch, function ($query) use ($request) { $searchTerm = "%{$request->multiSearch}%"; $query->where(function ($q) use ($searchTerm) { $q->whereLike('name', $searchTerm) ->orWhereHas('carrots', fn($q) => $q->whereLike('name', $searchTerm)); }); }) ->orderBy('id', 'asc'); // 分页获取主模型数据 $bunnies = $bunniesQuery->paginate( perPage: $request->get('pageSize', 5), page: $request->get('page', 1) ); // 延迟加载关联数据,替代原有的with,严格模式下完全可行 $bunnies->load([ 'carrots' => fn($query) => $request->carrotStatus ? $query->where('status', $request->carrotStatus) : $query, 'owner' ]);
关键优化点说明
1. 移除表名依赖,仅使用模型/关联名
- 用
whereHas('carrots')替代直接join操作,复用Bunny模型中定义的carrots关联关系(需确保模型已定义public function carrots()方法),无需手动编写表名、外键关联规则。 - 筛选兔子名称时直接写
whereLike('name'),因为当前查询上下文是Bunny模型,自动对应bunnies表的name字段。 - 去掉冗余的
select('bunnies.*'),Laravel模型查询默认会选择所有字段,符合需求时无需额外指定。
2. 替换with为load的可行性(严格模式兼容)
- 严格模式核心是禁止隐式的字段选择、未明确的关联加载,而
load()是主动触发的延迟加载,在获取主模型集合后明确加载关联数据,完全符合严格模式的规范,不会触发警告或错误。 - 分两步查询的优势:先通过
whereHas筛选出符合条件的兔子并分页,再加载关联数据,既保证分页总数的准确性,又避免了原代码中join+group by的冗余操作。
3. 其他细节优化
- 用
when()方法替代原有的空值判断逻辑,代码更简洁,符合Laravel查询构建器的最佳实践。 - 合并重复的
carrotStatus判断逻辑,whereHas负责筛选主模型,load闭包负责过滤关联的胡萝卜数据,逻辑分层更清晰。
内容的提问来源于stack exchange,提问作者inf3rno
相关产品推荐
相关产品推荐

