与主数据的多态关系
Polymorphic relationship with pivot data
我想解决以下问题:
我有多个模型,例如:
Product
Customer
每个模型应该能够有一个或多个 Fields
数据透视表。
Field
:
id
title
type
required
示例:
Product
有一个名为 video_url
的字段,type
应该是 string
包含 pivot
值 http://youtube.com/...
.
Customer
有一个名为 external_id
的字段,type
应该是 integer
包含 pivot
值 242
.
字段应由用户动态添加。用户应该能够决定该字段是否变形为 Product
或 Customer
(或更晚)。
也许这有助于理解:
我现在在做什么
目前我为每个创建了一个新模型,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');
}
}
目前这个问题解决了,但当然,这不是解决它的最优雅的方法。
我的问题
是否有可能将字段动态变形为 Product
或 Customer
并附加 pivot
?
最佳做法是使用单独的 table 来保存元信息,以便您可以根据需要轻松 add/remove "columns"
例如,您可以这样设置元数据 table:
create table `ProductField` (
products_id int(11),
column_name varchar(255),
value varchar(255),
)
然后在您的产品模型中,添加获取、插入、检查是否存在等功能
public function getMeta($column) {
$meta = DB::table('ProductField ')
->select('column_name', 'value')
->where('products_id', '=', $this->id)
->where('column_name', '=', $column)
->get();
if (!$meta->isEmpty()) {
return $meta;
} else {
return null;
}
}
public function addMeta($column, $value) {
DB::table('ProductField ')->insert(
[
'products_id' => $this->id,
'column_name' => $column,
'value' => $value,
]
);
}
同样,您也可以为客户实现动态特性。
你也可以使用数组存储字段,然后动态添加到模型中
foreach ($request->input('cost') as $key=>$cost) {
Price::create([
'product_id' => $request->product_id[$key],
'date' => Carbon::now(),
'cost' => $cost,
'trend' => 0
]);
}
如果您提前知道只会有某些动态字段,您可以选择为它们创建accessor methods
我想这就是你想要的Polymorphic:Many-to-Many
您不需要添加 ProductField
和 CustomerField
模型,
您只需添加 Product
、Customer
和 Field
模型。
这些字段将 动态属于产品或客户 fieldable_type
。即使您有更多模型,它也会将模型名称存储到此 fieldable_type
.
你需要像下面这样创建 tables:
fieldables
table 有 fieldable_id
和 fieldable_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);
我想解决以下问题:
我有多个模型,例如:
Product
Customer
每个模型应该能够有一个或多个 Fields
数据透视表。
Field
:
id
title
type
required
示例:
Product
有一个名为 video_url
的字段,type
应该是 string
包含 pivot
值 http://youtube.com/...
.
Customer
有一个名为 external_id
的字段,type
应该是 integer
包含 pivot
值 242
.
字段应由用户动态添加。用户应该能够决定该字段是否变形为 Product
或 Customer
(或更晚)。
也许这有助于理解:
我现在在做什么
目前我为每个创建了一个新模型,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');
}
}
目前这个问题解决了,但当然,这不是解决它的最优雅的方法。
我的问题
是否有可能将字段动态变形为 Product
或 Customer
并附加 pivot
?
最佳做法是使用单独的 table 来保存元信息,以便您可以根据需要轻松 add/remove "columns"
例如,您可以这样设置元数据 table:
create table `ProductField` (
products_id int(11),
column_name varchar(255),
value varchar(255),
)
然后在您的产品模型中,添加获取、插入、检查是否存在等功能
public function getMeta($column) {
$meta = DB::table('ProductField ')
->select('column_name', 'value')
->where('products_id', '=', $this->id)
->where('column_name', '=', $column)
->get();
if (!$meta->isEmpty()) {
return $meta;
} else {
return null;
}
}
public function addMeta($column, $value) {
DB::table('ProductField ')->insert(
[
'products_id' => $this->id,
'column_name' => $column,
'value' => $value,
]
);
}
同样,您也可以为客户实现动态特性。
你也可以使用数组存储字段,然后动态添加到模型中
foreach ($request->input('cost') as $key=>$cost) {
Price::create([
'product_id' => $request->product_id[$key],
'date' => Carbon::now(),
'cost' => $cost,
'trend' => 0
]);
}
如果您提前知道只会有某些动态字段,您可以选择为它们创建accessor methods
我想这就是你想要的Polymorphic:Many-to-Many
您不需要添加 ProductField
和 CustomerField
模型,
您只需添加 Product
、Customer
和 Field
模型。
这些字段将 动态属于产品或客户 fieldable_type
。即使您有更多模型,它也会将模型名称存储到此 fieldable_type
.
你需要像下面这样创建 tables:
fieldables
table 有 fieldable_id
和 fieldable_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);