Laravel Polymorphic关系覆盖保存

时间:2017-03-22 14:32:31

标签: php laravel eloquent polymorphism

我对类别有多态关系,它们可以属于客户端或模板。

我尝试将模板中的类别分配给客户端。但它覆盖了我的模板类别。

类别模型

class Category extends Model
{

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

客户端模型

class Client extends Model
{
    public function categories()
    {
        return $this->morphMany(Category::class, 'categorisable');
    }
}

模板模型

class Template extends Model
{
    public function categories()
    {
        return $this->morphMany(Category::class, 'categorisable');
    }
}

这是我尝试将类别从模板复制到客户端的代码

$template = Template::find($request->get('template_id'));
$client = Client::find($request->get('client_id'));

// For this template, get all categories
foreach($template->categories as $category) {
    $client->categories()->save($category);
}

但是它覆盖了我的类别表中的两个类别。因此,将它们保存在客户端上,但将其从模板中删除。

1 个答案:

答案 0 :(得分:0)

这是有道理的。您的Category模型表有两列,一列是附加到的模型类型,另一列是id(可能是categorisable_type(类似于“App \ Models”) \ Template“)和categorisable_id(类似于”4“))。

因此,每次重新分配已存在的类别时,它会将这两列从模型模型重写为客户端模型(例如,它会更改为“App \ Models \ Client”和“6”)。 / p>

这里有几个选项:

1)您的关系类型实际上并不理想。你可以在这里使用简单的one2many。创建几个cateogries,然后在Template和Client模型上有一个category_id。这样,您就可以在模板和客户端上使用相同的类别。

2)如果您需要为每个模板或客户端附加多个类别,请使用many2many关系。其余类似于选项1,你将只有两个表,比如category_clientcategory_template,假设你遵循Laravel命名约定,但你真的可以使用任何东西,你只需要在关系方法中指定它。

3)你也可以使用many2many多态关系。您最终会得到clientstemplatescategoriescategorisable表格。 categories表只保留类别,categorisable将具有关系定义,类似于选项2.

4)如果你坚持在这里使用one2many多态关系(建议:不要),你可以为你指定的每个客户端克隆每个模板,但这没有任何意义,你实际上不会有与您的TemplateClient相关联的同一类别,只是原始版本的克隆,因此您无法从{{{{{}}反向访问多个templatesclient 1}},因为它们都属于不同的类别。

方法1和2实际上以正确的顺序颠倒整个关系,因为您当前的逻辑是反转的,并且如上所述,并不理想。

此处有更多信息 - https://laravel.com/docs/5.4/eloquent-relationships(对于Laravel 5.4,这是我写这篇文章时的最新版本。)