与枢轴数据的多态关系

SPQ*_*Inc 1 laravel eloquent laravel-6

我想解决以下问题:

我有多个模型,例如:

  • Product
  • Customer

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

Field

  • id
  • title
  • type
  • required

例子:

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

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

这些字段应由用户动态添加。用户应该能够决定,该字段是变形为Product还是Customer(或什至更晚)。

也许这有助于理解:

在此处输入图片说明

我现在在做什么

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

对于客户:

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

对于产品:

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

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

我的问题

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

Tsa*_*oga 6

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

你不需要添加ProductFieldCustomerField模型,

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

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

您需要像下面这样创建表:

在此处输入图片说明

fieldables表有fieldable_idfieldable_type;

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

Relation::morphMap([
    'products' => 'App\Product',
    'customers' => 'App\Customer',
]);
Run Code Online (Sandbox Code Playgroud)

在产品型号中:

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

在客户模型中:

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

现场模型:

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');
    }
}
Run Code Online (Sandbox Code Playgroud)

带有枢轴值的 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);
Run Code Online (Sandbox Code Playgroud)