You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 07:15:33