如何让Laravel Eloquent的inheritedEmployees返回Eloquent关联关系?
解决方法:让
inheritedEmployees返回Eloquent关联关系 要让这个方法返回可链式调用的Eloquent关联(而非集合),我们需要利用Eloquent的查询构造器能力,通过嵌套关联查询直接获取符合条件的员工,替代原来循环拼接集合的方式。这样既能避免N+1查询的性能问题,又能支持后续追加任意查询条件。
步骤1:替换原方法代码
在Office模型中把inheritedEmployees方法改成如下实现:
// Office model public function inheritedEmployees() { // 如果是大型办公室(major),直接返回空的查询构造器 if ($this->is_major) { return \App\Model\Employee::query()->whereDoesntExist(); } // 构建关联查询:获取当前小型办公室关联的所有大型办公室下的员工 return \App\Model\Employee::query() ->whereHas('offices', function ($officeQuery) { // 筛选出与当前小型办公室绑定的大型办公室 $officeQuery->whereHas('minors', function ($minorQuery) { $minorQuery->where('minors.id', $this->id); }); }) ->distinct(); // 去重,避免同一员工属于多个大型办公室时重复返回 }
为什么这样改?
- 返回可链式的构造器:现在这个方法返回的是
Illuminate\Database\Eloquent\Builder实例,和你用$office->employees()得到的关联类型完全一致,支持所有Eloquent查询方法(where、orderBy、with等)。 - 性能大幅提升:原方法是循环每个大型办公室并加载其员工,属于典型的N+1查询;新方法通过一次嵌套查询完成所有操作,数据库请求次数大幅减少。
- 逻辑完全对齐:
distinct()替代了原方法的unique('id'),确保员工不会重复返回;whereDoesntExist()保证大型办公室返回空结果,和原逻辑保持一致。
使用示例
现在你可以像使用普通关联一样自由追加查询条件了:
// 筛选继承员工中职位为医生或牙医的 $qualifiedInherited = $minorOffice->inheritedEmployees()->whereHas('qualifications', function ($query) { $query->whereIn('job', ['doctor', 'dentist']); })->get(); // 还可以排序、关联预加载 $sortedInherited = $minorOffice->inheritedEmployees() ->orderBy('first_name') ->with('qualifications') ->get();
内容的提问来源于stack exchange,提问作者DatsunBing
相关产品推荐
相关产品推荐

