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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 06:32:44