Laravel中如何通过Eloquent模型实现基于数据透视表过滤的假期数据查询
用Laravel Eloquent实现指定经理下属用户的假期查询
嘿,我来帮你把原来的DB查询构造器写法转换成更优雅的Eloquent实现~首先得先修正模型里的一个小细节,然后再看两种不同的查询方式:
第一步:修正模型关联的透视表名
你描述里的透视表是user_manager,但当前Manager和User模型里的关联用的是employee_manager,这会导致关联找不到数据,先把这个改掉:
修改Manager模型:
class Manager extends Model { use HasFactory; protected $table = 'managers'; protected $fillable = ['user_id']; public function users() { // 把第二个参数改成你的透视表名user_manager return $this->belongsToMany(User::class, 'user_manager')->withTimestamps(); } }
修改User模型:
class User extends Model { use HasFactory, Notifiable; public function managers() { // 同样改成user_manager return $this->belongsToMany(Manager::class, 'user_manager')->withTimestamps(); } // 新增与Vacation模型的关联(因为要通过用户找假期) public function vacations() { return $this->hasMany(Vacation::class, 'user_id'); } }
第二步:两种Eloquent查询方式
方式一:从Vacation模型出发(推荐,单查询更高效)
直接通过whereHas嵌套关联,筛选出属于指定经理下属用户的假期:
$managerId = $id; // 你的指定manager id $vacations = Vacation::whereHas('user.managers', function ($query) use ($managerId) { $query->where('managers.id', $managerId); })->get();
这个写法会生成一条高效的SQL查询,直接过滤出符合条件的假期,避免N+1问题。
方式二:从Manager模型出发
如果你想先拿到经理对象,再获取其下属的所有假期,可以这么写:
$manager = Manager::findOrFail($id); // 先获取经理的所有用户,预加载假期,再提取并合并所有假期 $vacations = $manager->users() ->with('vacations') // 预加载避免N+1 ->get() ->pluck('vacations') // 提取每个用户的假期集合 ->flatten(); // 把多维集合转成一维
这种写法更直观,但如果下属用户很多,会先查询用户,再批量查询假期(因为用了with,所以是2条查询),性能也不错,适合需要同时处理用户和假期数据的场景。
内容的提问来源于stack exchange,提问作者Fuksik64
相关产品推荐
相关产品推荐

