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

如何用Eloquent关系实现指定诊所科室查询?该方案是否值得?

使用Eloquent关系实现多诊所科室查询的方案分析

一、怎么用Eloquent关系实现需求

嘿,你的三张表其实对应了诊所(Clinic)和科室(Department)的多对多关系,中间表clinics_in_departments就是用来关联两者的桥梁。我们先在模型里把这个关系定义好,之后查询会变得非常简洁直观。

1. 定义模型关联

先在Clinic模型中添加和Department的多对多关系:

// app/Models/Clinic.php
public function departments()
{
    // 参数依次是:关联模型、中间表名、当前模型在中间表的外键、关联模型在中间表的外键
    return $this->belongsToMany(Department::class, 'clinics_in_departments', 'clinic_id', 'department_id');
}

如果后续需要从科室反向查询诊所,也可以在Department模型里补上反向关联(可选,但实用性很高):

// app/Models/Department.php
public function clinics()
{
    return $this->belongsToMany(Clinic::class, 'clinics_in_departments', 'department_id', 'clinic_id');
}

2. 两种实用的查询方式

方式一:直接筛选关联指定诊所的科室(推荐)

这种方式会生成高效的SQL子查询,直接返回去重后的科室集合,性能和手动写join几乎一致:

$departments = Department::whereHas('clinics', function ($query) {
    $query->whereIn('id', [1, 2, 3]);
})->get();

方式二:从诊所出发预加载科室

如果需要同时获取诊所信息,或者想从诊所维度入手查询,可以用预加载+数据提取的方式:

// 获取指定诊所并预加载关联的科室,避免N+1查询
$clinics = Clinic::whereIn('id', [1,2,3])->with('departments')->get();
// 提取所有科室并去重(避免同一个科室关联多个诊所时重复出现)
$departments = $clinics->pluck('departments')->flatten()->unique('id');

二、这个方案是否值得采用?

绝对值得!但咱们得结合场景聊聊它的优势和注意点:

优势

  • 语义化拉满:对比手动写join的代码,whereHas('clinics')一眼就能看懂是要找关联了指定诊所的科室,可读性极强,后续维护代码的人能快速理解逻辑。
  • 维护成本低:如果后续中间表结构调整(比如加字段、改表名),只需要修改模型里的关联定义,不用去改所有用到这个查询的地方。
  • 扩展性强:Eloquent关系自带预加载、延迟加载、附加/分离关联等特性,后续如果要给科室加其他关联数据(比如科室医生),直接链式调用with('doctors')就行,非常灵活。

注意点

  • 方式二的flatten()->unique()在诊所数量多、科室重复率高的情况下,会有一点点内存开销,这时候优先用方式一的子查询写法,性能更优。
  • 极端复杂的自定义查询场景下,手动写join可能更灵活,但你的这个需求属于标准多对多查询,Eloquent完全能胜任,生成的SQL效率和手动写的几乎没差。

总的来说,用Eloquent关系实现这个需求是非常合适的,既符合Laravel的设计理念,又能大幅提升代码的可维护性。

内容的提问来源于stack exchange,提问作者Ostap Brehin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:46:01