Kev*_*cio 6 php attributes field dynamic laravel
我想问如何在模型类上创建动态属性。假设我有一个如下代码所示的表结构。
Schema::create('materials', function (Blueprint $table) {
$table->increments('id');
$table->string('sp_number');
$table->string('factory');
$table->text('dynamic_fields')->comment('All description of the material will saved as json');
$table->timestamps();
});
Run Code Online (Sandbox Code Playgroud)
我的表结构中有一个名为“dynamic_fields”的列,它将保存字段的 JSON 字符串。下面是 JSON 结构的示例。
[
{
"name":"COLOR WAY",
"value":"ASDFF12"
},
{
"name":"DESCRIPTION",
"value":"agg2sd12"
},
{
"name":"REF NUM",
"value":"121312"
}
]
Run Code Online (Sandbox Code Playgroud)
我想从动态字段访问字段,例如“COLOR WAY”。
在我的模型中,我想像这样访问动态字段上的“COLOR WAY”字段
$material->color_way;
Run Code Online (Sandbox Code Playgroud)
有人能告诉我该怎么做吗?
如果您提前知道只会存在某些动态字段,则可以选择为它们创建访问器方法。例如,您可以将其添加到您的模型中:
// Dynamic fields must be cast as an array to iterate through them as shown below
protected $casts = [
'dynamic_fields' => 'array'
];
// ...
public function getColorWayAttribute()
{
foreach ($this->dynamic_fields as $field) {
if ($field['name'] === 'COLOR WAY') {
return $field['value'];
}
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
这将允许您执行以下操作:
$colorWay = $material->color_way;
Run Code Online (Sandbox Code Playgroud)
或者,如果您的组合dynamic_fields
不受限制,可能有很多组合,或者您希望有更大的灵活性以便能够添加更多组合并让它们可访问,您可以重写getAttribute
Laravel 模型类的方法。
// Dynamic fields must be cast as an array to iterate through them as shown below
protected $casts = [
'dynamic_fields' => 'array'
];
// ...
public function getAttribute($key)
{
$attribute = parent::getAttribute($key);
if ($attribute === null && array_key_exists('dynamic_fields', $this->attributes)) {
foreach ($this->dynamic_fields as $dynamicField) {
$name = $dynamicField['name'];
if (str_replace(' ', '_', mb_strtolower($name)) === $key) {
return $dynamicField['value'];
}
}
}
return $attribute;
}
Run Code Online (Sandbox Code Playgroud)
这种方法调用 Laravel 的实现,getAttribute
它首先检查您是否定义了实际的属性,或者是否为该属性定义了访问器(就像我的第一个建议一样),然后检查基模型类上是否存在具有该名称的方法,并且然后最后尝试加载一个关系(如果您定义了一个关系)。
当这些方法中的每一个都失败(null
返回)时,我们然后检查dynamic_fields
模型中是否有属性。如果有,我们循环遍历每个动态字段(假设您的动态字段dynamic_fields
被转换为array
),然后将定义的动态字段的名称转换为小写并用下划线替换空格。然后,我们最后检查刚刚派生的名称是否与提供的键匹配,如果匹配,我们返回该值。如果没有,原件$attribute
将被退回,即null
.
这将允许您获取任何动态字段,就好像它们被定义为类中的属性一样。
$colorWay = $material->color_way;
$description = $material->description;
$refNum = $material->ref_num;
Run Code Online (Sandbox Code Playgroud)
请注意:我尚未测试此代码,很可能存在一两个问题。尝试一下,看看它是否适合您。另请注意,这仅适用于获取动态字段,设置它们将需要重写另一个方法。
尝试在您的模型中使用此代码:
protected $casts = [
'dynamic_fields' => 'array',
];
public function setAttribute($key, $value)
{
if (!$this->getOriginal($key)) {
$this->dynamic_fields[$key] = $value;
}
parent::setAttribute($key, $value);
}
public function getAttribute($key)
{
if (!$this->getOriginal($key)) {
return $this->dynamic_fields[$key]
}
parent::getAttribute($key);
}
Run Code Online (Sandbox Code Playgroud)