问题描述
我使用了 Laravel documentation 中描述的一对多多态关系,以便能够将不同的父模型关联到一个子模型。我假设,我可以将不同的父模型分配给同一个子模型。但这不起作用。一旦我与同一个孩子的另一个父模型创建了一个新关系,旧的关系就会被替换。
示例:
A
、B
和 C
是父模型,每个模型都有一个数据记录 (id=1
)。
X
是具有一条数据记录 (id=1
) 的子模型
我不能用常用方法做这样的事情:
A
(id=1
) X
(id=1
)
B
(id=1
) X
(id=1
)
C
(id=1
) X
(id=1
)
因为最后一个关系的创建总是覆盖前一个。在此示例中,将保留一个关系 (C
(id=1
) X
(id=1
))
我可以通过多对多的多态实现来做到这一点——但这实际上不是我想要的,因为我不希望父模型能够与子模型有多个关系。 (虽然我可以通过在相应字段的 *able
表中创建组合键来排除这种情况)
这是实际代码,它应该将一个图像分配给多个父模型(但只保留循环中的最后一个保存 - 如果我在循环末尾添加一个中断,则保存第一个):>
public function store(StoreImageRequest $request)
{
$validated = $request->validated();
$image = $validated['image'];
$name = isset($validated['clientName']) ? $image->getClientOriginalName() : $validated['name'];
$fileFormat = FileFormat::where('mimetype','=',$image->getClientMimeType())->first();
$path = $image->store('images');
$imageModel = Image::make(['name' => $name,'path' => $path])->fileFormat()->associate($fileFormat);
$imageModel->save();
$relatedModels = Image::getRelatedModels();
foreach($relatedModels as $fqcn => $cn) {
if(isset($validated['model'.$cn])) {
$id = $validated['model'.$cn];
$models[$fqcn] = call_user_func([$fqcn,'find'],[$id])->first();
$models[$fqcn]->images()->save($imageModel);
}
}
}
解决方法
在我看来,您将一对多关系转向了错误的方向。
您的子模型应该实现 morphTo
,而您的父模型应该实现 morphMany
a
id - integer
title - string
body - text
b
id - integer
title - string
url - string
c
id - integer
title - string
url - string
x
id - integer
body - text
commentable_id - integer
commentable_type - string
子模型
public class X extends Model
{
public function commentable(): MorphTo
{
return $this->morphTo();
}
}
父模型
public class A extends Model
{
public function comments(): MorphMany
{
return $this->morphMany(X::class,'commentable');
}
}
添加到关系:
$a = A::firstOrFail();
$x = X::firstOrFail();
// Attaches
$a->comments()->attach($x);
// Sync,removes the existing attached comments
$a->comments()->sync([$x]);
// Sync,but do not remove existing
$a->comments()->sync([$x],false);
$a->comments()->syncWithoutDetaching([$x]);