如何获取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_id | view_mode | shareable_type | shareable_id |
|---|---|---|---|
| 1 | RW | App\Models\A | 1 |
| 1 | R | App\Models\A | 2 |
| 1 | W | App\Models\B | 5 |
| 2 | R | App\Models\A | 2 |
| 1 | W | App\Models\C | 8 |
预期获取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'); }
错误原因
- Shareable模型关联定义错误:中间表是多态多对多的关联表,不需要在Shareable模型中定义
morphedByMany类型的a()方法,正确的关联是已定义的shareable()(morphTo),用于关联到具体的A/B/C实体。 - 关联加载错误:User的
shared方法中使用with('a')是错误的,应该加载shareable关联才能获取对应的实体。 - 复合主键未指定:中间表使用复合主键(
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模型获取数据,修正如下:
- 修正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(); }
- 修正User模型的shared关联:
// User.php public function shared() { return $this->hasMany(Shareable::class)->with('shareable'); }
- 调用并整理数据:
$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
相关产品推荐
相关产品推荐

