You need to enable JavaScript to run this app. Laravel 如何按所属州查询关联用户 无需单独调用City模型
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 如何按所属州查询关联用户 无需单独调用City模型

Eloquent 查询指定州下关联城市对应用户的优化实现

问题背景

  • 表结构关联关系:
    • users 表包含外键字段city_id,关联城市表主键
    • cities 表包含外键字段state_id,关联所属州的主键
  • 需求:在现有用户筛选逻辑中增加按州过滤能力,筛选出属于指定州下所有城市对应的用户

初始代码框架

$users = User::role('company')
            ->when((int) $state, function ($query, $state) {
                // 待实现的按州筛选逻辑
            })
            ->when((int) $city, function ($query, $city) {
                return $query->where('city_id', $city);
            })
            ->get();

已尝试的实现

原实现逻辑:先单独调用City模型查出对应州下所有城市的id集合,再通过whereIn匹配用户的city_id字段

$users = User::role('company')
            ->when((int) $state, function ($query, $state) {
                $cities = City::where('state_id', $state)
                            ->pluck('id')
                            ->toArray();
                return $query->where('city_id', $cities);
            })
            ->when((int) $city, function ($query, $city) {
                return $query->where('city_id', $city);
            })
            ->get();

该方案可以正常返回结果,但会产生两次数据库交互(一次拉取城市id数组到PHP端、一次查询用户),属于冗余查询,需要优化为无单独City模型调用的实现方式。

优化实现方案

两种无需单独调用City模型的实现方式都可以完成单SQL筛选,避免冗余查询:

方案1:基于模型关联的whereHas实现

前提:User模型已定义与City的关联方法(即city()方法返回belongsTo(City::class))

$users = User::role('company')
            ->when((int) $state, function ($query, $state) {
                // 直接通过关联关系完成筛选,不需要手动查询城市id集合
                $query->whereHas('city', function ($cityQuery) use ($state) {
                    $cityQuery->where('state_id', $state);
                });
            })
            ->when((int) $city, function ($query, $city) {
                return $query->where('city_id', $city);
            })
            ->get();
  • 特点:写法简洁,符合Eloquent的关联编程规范,所有筛选逻辑下推到数据库层,无多余PHP端数据处理。

方案2:子查询实现(无关联依赖)

如果不想依赖模型关联定义,可以直接通过闭包子查询完成城市id匹配,效果与方案1完全一致:

$users = User::role('company')
            ->when((int) $state, function ($query, $state) {
                $query->whereIn('city_id', function ($subQuery) use ($state) {
                    // 子查询直接在数据库层运行,不会将城市id数组拉取到PHP端
                    $subQuery->select('id')
                            ->from('cities')
                            ->where('state_id', $state);
                });
            })
            ->when((int) $city, function ($query, $city) {
                return $query->where('city_id', $city);
            })
            ->get();
  • 特点:不依赖模型关联定义,直接通过表结构实现筛选,执行效率与whereHas基本一致。

内容的提问来源于stack exchange,提问作者Andreas Hunter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 19:36:08