Laravel多态关联:用Type表ID存储addressable_type并解决关联失效
解决Laravel多态关联使用Type表ID替代模型类名的问题
要让你的多态关联正常工作,需要修改Address和Convoy模型的关联方法,适配addressable_type存储Type表ID的自定义逻辑:
1. 修改Address模型的morphTo关联
默认的morphTo会直接用addressable_type的值作为模型类名,现在需要先通过这个ID查询Type表拿到对应的模型类名,再关联目标模型:
class Address extends Model { use HasFactory; protected $guarded = []; public function addressable() : MorphTo { return $this->morphTo()->resolveUsing(function ($typeId, $modelId) { // 通过Type ID获取对应的模型类名 $typeRecord = Type::find($typeId); if (!$typeRecord) { return null; } $modelClass = $typeRecord->type; // 返回对应模型实例 return $modelClass::find($modelId); }); } public function status() : BelongsTo { return $this->belongsTo(Status::class); } }
2. 修改Convoy模型的morphOne关联
默认的morphOne会把Convoy的类名作为addressable_type的查询条件,现在需要替换成对应Type表的ID:
class Convoy extends Model { use HasFactory; protected $guarded = []; public function address() : MorphOne { // 获取Convoy对应的Type表ID $convoyTypeId = Type::where('type', self::class)->value('id'); // 关联Address时指定addressable_type为Type ID return $this->morphOne(Address::class, 'addressable') ->where('addressable_type', $convoyTypeId); } }
额外优化:全局复用类型ID获取逻辑
如果多个模型都需要这种关联方式,可以在Type模型中添加静态方法统一获取类型ID:
class Type extends Model { use HasFactory; public static function getTypeIdForModel(string $modelClass) : ?int { return static::where('type', $modelClass)->value('id'); } }
然后Convoy模型的address方法可以简化为:
public function address() : MorphOne { $convoyTypeId = Type::getTypeIdForModel(self::class); return $this->morphOne(Address::class, 'addressable') ->where('addressable_type', $convoyTypeId); }
验证效果
修改完成后,重新执行你的控制器代码:
$test = Convoy::with('address')->find(6); dd($test);
此时address关联应该能正确返回对应的地址数据。
内容的提问来源于stack exchange,提问作者poxantidote
相关产品推荐
相关产品推荐

