Laravel Eloquent:用多对多模拟一对多,如何简洁获取同白标用户?
优化Laravel多对多模拟一对多的同白标用户查询
嘿,这个场景我太熟悉了!用多对多关联来模拟一对多,既保留了表结构的干净,又满足了业务需求,确实是个聪明的做法。咱们来把你现有的代码变得更简洁、更贴合Laravel的优雅风格~
先说说现有代码的小问题
你当前的写法里多次调用了auth()->user()->whitelabel->first(),这会导致重复查询数据库;而且用whereIn配合pluck('id')的方式,虽然能实现功能,但没有充分利用Eloquent关联的强大能力。
几种更Laravel范儿的写法
写法一:直接利用关联关系快速获取
既然每个用户只关联一个白标,你可以直接通过白标的users关联拿到同白标的所有用户,还能方便地排除当前用户:
// 获取同白标用户(包含自己) $sameWhitelabelUsers = auth()->user()->whitelabels->first()->users; // 排除当前用户,更符合业务场景 $sameWhitelabelUsers = auth()->user()->whitelabels->first() ->users() ->where('id', '!=', auth()->id()) ->get();
这里注意用users()(关联方法)而不是users(关联属性),这样可以继续链式添加查询条件(比如分页、筛选字段等)。
写法二:用whereHas通过关联筛选用户
如果需要从User模型出发查询,whereHas是Eloquent的经典用法,语义化更强:
$sameWhitelabelUsers = User::whereHas('whitelabels', function ($query) { $query->where('id', auth()->user()->whitelabels->first()->id); }) ->where('id', '!=', auth()->id()) ->get();
写法三:通过中间表关联查询,性能更优
如果追求极致性能,可以直接通过中间表做关联查询,减少ORM的查询层级:
$sameWhitelabelUsers = User::join('user_whitelabel', 'users.id', '=', 'user_whitelabel.user_id') ->where('user_whitelabel.whitelabel_id', auth()->user()->whitelabels()->first()->id) ->where('users.id', '!=', auth()->id()) ->select('users.*') // 避免重复字段 ->get();
进阶优化:给User模型加便捷方法
为了让代码更复用,你可以在User模型里封装一个方法,以后调用就一句话的事:
// 在app/Models/User.php中添加 public function sameWhitelabelUsers() { // 先确保用户有白标关联 if (!$this->whitelabels->count()) { return collect(); // 返回空集合避免报错 } return $this->whitelabels->first() ->users() ->where('id', '!=', $this->id) ->get(); } // 调用时直接用 $sameWhitelabelUsers = auth()->user()->sameWhitelabelUsers();
小提醒:避免N+1查询问题
如果你的业务中经常用到这个查询,记得提前预加载whitelabels关联,避免重复查询数据库:
// 登录后或者在需要的地方预加载 $user = auth()->user()->load('whitelabels'); // 之后再调用关联就不会重复查询了 $sameWhitelabelUsers = $user->sameWhitelabelUsers();
内容的提问来源于stack exchange,提问作者simonw16
相关产品推荐
相关产品推荐

