首页 > 解决方案 > 与枢轴数据的多态关系

问题描述

我想解决以下问题:

我有多个模型,例如:

每个模型都应该能够拥有一个或多个Fields数据透视数据。

Field

例子:

Product有一个名为 的字段video_urltype应该string包含该pivothttp://youtube.com/...

Customer有一个名为 的字段external_idtype应该integer包含该pivot242

字段应由用户动态添加。用户应该能够决定该字段是否正在变形ProductCustomer(甚至更晚)。

也许这有助于理解:

在此处输入图像描述

我现在在做什么

目前我为每个人创建了一个新模型,product并且customer

对于客户:

class CustomerField extends Model
{
    /**
     * @return \Illuminate\Database\Eloquent\Relations\belongsToMany
     */
    public function customers()
    {
        return $this->belongsToMany(Customer::class)->withPivot('value');
    }
}

对于产品:

class ProductField extends Model
{
    /**
     * @return \Illuminate\Database\Eloquent\Relations\belongsToMany
     */
    public function products()
    {
        return $this->belongsToMany(Product::class)->withPivot('value');
    }
}

目前这可行,但当然,这不是解决它的最优雅的方法。

我的问题

是否有可能将一个字段动态地变形为ProductCustomer附加一个pivot

标签: laraveleloquentlaravel-6

解决方案


我认为这就是你想要的多态:多对多

你不需要添加ProductFieldCustomerField模型,

您只需要添加Product,CustomerField模型。

这些字段将动态地属于产品或客户 fieldable_type。即使您有更多模型,它也会将模型名称存储到 this fieldable_type

您需要创建的表如下所示:

在此处输入图像描述

fieldables表有fieldable_idfieldable_type

fieldable_type将自动设置您的模型名称,例如App\Product,您可以在以下位置自行自定义AppServiceProvider

Relation::morphMap([
    'products' => 'App\Product',
    'customers' => 'App\Customer',
]);

在产品型号中:

class Product extends Model
{
    /**
     * Get all of the fields for the product.
     */
    public function fields()
    {
        return $this->morphToMany('App\Field', 'fieldable')->withPivot('value');
    }
}

在客户模型中:

class Customer extends Model
{
    /**
     * Get all of the fields for the customer.
     */
    public function fields()
    {
        return $this->morphToMany('App\Field', 'fieldable')->withPivot('value');
    }
}

在现场模型中:

class Field extends Model
{
    /**
     * Get all of the products that are assigned this field.
     */
    public function products()
    {
        return $this->morphedByMany('App\Product', 'fieldable');
    }

    /**
     * Get all of the customers that are assigned this field.
     */
    public function customers()
    {
        return $this->morphedByMany('App\Customer', 'fieldable');
    }
}

具有枢轴值的 CRUD:

之后,您可以轻松地创建、获取、更新、删除枢轴值,例如:

Field::first()->products; # return the products with pivot value
Field::first()->customers; # return the customers with pivot value
Customer::first()->fields;

$field = Field::first();
# create new relationship with pivot value between customer and fields:
Customer::first()->fields()->attach($field, ['value' => 'customer new value field']);
# update pivot with value:
Customer::first()->fields()->sync([$field->id => ['value' => 'update customer value field']]);
# Delete pivot
Customer::first()->fields()->detach($field->id);

推荐阅读