Laravel两端多态多对多关联查询实现方法咨询
问题描述
我有4个模型:
- 协议类:
RegulatedAgreement和LeasingAgreement - 承包商类:
Associate和Executive
中间表的迁移结构如下:
Schema::create('agreement_contractor', static function (Blueprint $table) { $table->nullableMorphs('agreement'); $table->nullableMorphs('contractor'); });
我希望调用 $regulatedAgreement->contractors 时,能获取到所有关联的承包商(包含Associate和Executive实例),请问该怎么实现?
我试过创建继承自Model、Pivot甚至MorphPivot的自定义中间表模型,但没理清思路,也不确定该用哪种关联关系。
解决方案
你需要在协议类中定义双多态多对多关联,同时指定目标承包商的模型类型,具体实现步骤如下:
1. 在协议模型中定义关联方法
以RegulatedAgreement为例,在模型中添加contractors关联方法:
// app/Models/RegulatedAgreement.php use App\Models\Associate; use App\Models\Executive; public function contractors() { return $this->morphToMany( \Illuminate\Database\Eloquent\Model::class, 'agreement', 'agreement_contractor' )->whereIn('contractor_type', [ Associate::class, Executive::class ]); }
同样的,把这个方法复制到LeasingAgreement模型中即可。
2. 确保返回具体模型实例(可选优化)
上述方法返回的是基础Model实例集合,你可以添加访问器,自动转换为对应的承包商模型实例:
// 补充到协议模型中 public function getContractorsAttribute() { return $this->contractors()->get()->map(function ($item) { return app($item->contractor_type)->find($item->contractor_id); }); }
3. 反向关联(可选)
如果需要从承包商模型访问关联的协议(比如$associate->agreements),可以在Associate和Executive中定义:
// app/Models/Associate.php use App\Models\RegulatedAgreement; use App\Models\LeasingAgreement; public function agreements() { return $this->morphToMany( \Illuminate\Database\Eloquent\Model::class, 'contractor', 'agreement_contractor' )->whereIn('agreement_type', [ RegulatedAgreement::class, LeasingAgreement::class ]); }
关键说明
- 这里使用
morphToMany是因为中间表是双多态结构(agreement和contractor均为多态字段),完全适配你的表结构。 - 当前场景不需要自定义
MorphPivot,除非你需要在中间表存储额外字段并直接访问,基础的morphToMany足以满足需求。 whereIn用来过滤指定的模型类型,确保只返回你需要的Associate和Executive实例。
内容的提问来源于stack exchange,提问作者Cordellito
相关产品推荐
相关产品推荐

