Laravel嵌套多对多关联下如何获取带area、city的users数据
Laravel 嵌套关联预加载实现方案
直接使用Eloquent提供的嵌套预加载点语法即可,不需要修改你已经定义好的模型关联,只需要调整with()方法内的关联传参,就能一次性把分类、关联用户、用户关联区域、区域关联城市的数据全部查出来,全程不会产生N+1查询问题。
核心实现代码
首先确认你三个模型的关联方法名和已定义的一致:
- Category 模型多对多关联 User 的方法名为
users()(和你原有代码保持一致即可) - User 模型多对多关联 Area 的方法名为
areas()(如果你的方法名是其他名称,替换成对应名称即可) - Area 模型与 City 模型的关联方法名按你实际定义填写:如果是City作为一方、Area作为多方(即一个城市包含多个区域),Area内的反向关联方法一般命名为
city();如果是Area作为一方、City作为多方,Area内的一对多关联方法一般命名为cities(),后续预加载参数替换成你实际的方法名即可。
以下示例默认按常规业务逻辑(一个City包含多个Area,Area归属于单个City)编写,关联名为
city(),如果你的关联方向相反,把参数里的city替换为cities即可。
修改查询代码如下:
$categories = Category::where('id', $id) ->with('users.areas.city') ->get();
上述写法会自动按层级预加载全部关联数据,不需要额外单独写with('users')、with('users.areas'),Eloquent会自动处理父级关联的预加载,不会产生重复查询。
返回数据调用示例
查询完成后你可以直接按关联层级遍历取数据,不需要额外执行查询:
foreach ($categories as $category) { // 操作分类数据 例如 $category->category_name foreach ($category->users as $user) { // 操作用户数据 例如 $user->nickname foreach ($user->areas as $area) { // 操作区域数据 例如 $area->area_name // 直接取当前区域关联的城市数据 例如 $area->city->city_name } } }
带约束的预加载写法
如果你需要对某一层关联加筛选条件,比如只取状态正常的用户、只取启用的区域,可以用数组结构传参定义查询约束:
$categories = Category::where('id', $id) ->with([ 'users' => function ($userQuery) { $userQuery->where('status', 1); // 筛选状态为正常的用户 }, 'users.areas' => function ($areaQuery) { $areaQuery->where('is_enabled', 1); // 筛选启用状态的区域 }, 'users.areas.city' ]) ->get();
内容的提问来源于stack exchange,提问作者Hossam
相关产品推荐
相关产品推荐

