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

如何获取Laravel模型的所有多态关联数据?

问题:多态多对多关联数据获取失败排查

场景与现有代码

已在Laravel中设置User模型与A、B、C三个模型的多态多对多关联,模型代码如下:

// User.php
public function a(): MorphToMany
{
    return $this->morphedByMany(A::class, 'shareable')->withPivot('view_mode');
}

public function b(): MorphToMany
{
    return $this->morphedByMany(B::class, 'shareable')->withPivot('view_mode');
}

public function c(): MorphToMany
{
    return $this->morphedByMany(C::class, 'shareable')->withPivot('view_mode');
}

// A.php、B.php、C.php
public function users(): MorphToMany
{
    return $this->morphToMany(User::class, 'shareable');
}

对应的中间表shareables数据如下:

user_idview_modeshareable_typeshareable_id
1RWApp\Models\A1
1RApp\Models\A2
1WApp\Models\B5
2RApp\Models\A2
1WApp\Models\C8

预期获取ID为1的User所有关联内容格式:

relations: [
    a: [
        - A entity with id 1
        - A entity with id 2
    ],
    b: [
        - B entity with id 5
    ],
    c: [
        - C entity with id 8
    ]
]

错误尝试与问题

尝试创建Shareable模型并添加关联,但调用$user->shared得到空集合,无法获取关联实例:

// Shareable.php
protected $table = 'shareables';

public function shareable()
{
    return $this->morphTo();
}

public function a()
{
    return $this->morphedByMany(A::class, 'shareable');
}

// User.php新增方法
public function shared()
{
    return $this->hasMany(Shareable::class)->with('a');
}

错误原因

  1. Shareable模型关联定义错误:中间表是多态多对多的关联表,不需要在Shareable模型中定义morphedByMany类型的a()方法,正确的关联是已定义的shareable()(morphTo),用于关联到具体的A/B/C实体。
  2. 关联加载错误:User的shared方法中使用with('a')是错误的,应该加载shareable关联才能获取对应的实体。
  3. 复合主键未指定:中间表使用复合主键(user_id、shareable_type、shareable_id),未在Shareable模型中声明会导致Eloquent无法正确识别关联关系。

解决方法

方法一:直接利用已定义的多态关联(推荐)

已经在User模型中定义了a()、b()、c()三个多态多对多关联,直接加载即可得到预期数据:

// 获取用户并加载所有关联
$user = User::find(1)->load(['a', 'b', 'c']);

// 整理成预期格式
$relations = [
    'a' => $user->a,
    'b' => $user->b,
    'c' => $user->c,
];

方法二:修复Shareable模型关联

如果需要通过Shareable模型获取数据,修正如下:

  1. 修正Shareable模型:
// Shareable.php
protected $table = 'shareables';
public $incrementing = false; // 因为无自增主键
protected $primaryKey = ['user_id', 'shareable_type', 'shareable_id']; // 声明复合主键

public function user()
{
    return $this->belongsTo(User::class);
}

public function shareable()
{
    return $this->morphTo();
}
  1. 修正User模型的shared关联:
// User.php
public function shared()
{
    return $this->hasMany(Shareable::class)->with('shareable');
}
  1. 调用并整理数据:
$user = User::find(1);
$sharedItems = $user->shared;

// 分组整理成预期格式
$relations = [
    'a' => $sharedItems->where('shareable_type', A::class)->pluck('shareable'),
    'b' => $sharedItems->where('shareable_type', B::class)->pluck('shareable'),
    'c' => $sharedItems->where('shareable_type', C::class)->pluck('shareable'),
];

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 12:35:20