Laravel模型动态属性 [英] Laravel Model Dynamic Attribute

查看:373
本文介绍了Laravel模型动态属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想问一下如何在模型类上创建动态属性.假设我有一个像下面的代码这样的表结构.

I would like to ask if how to create a dynamic attribute on the model class. Let's suppose I have a table structure like below code.

   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();
    });

我的表结构中有一列名为"dynamic_fields",其中将包含字段的JSON字符串.下面是JSON结构的示例.

I have a column in my table structure named "dynamic_fields" that will hold a JSON string for the fields. An example of JSON structure below.

[  
   {  
      "name":"COLOR WAY",
      "value":"ASDFF12"
   },
   {  
      "name":"DESCRIPTION",
      "value":"agg2sd12"
   },
   {  
      "name":"REF NUM",
      "value":"121312"
   }
]

因此,我想从动态字段(例如"COLOR WAY")访问字段. 在我的模型中,我想像这样访问动态字段上的"COLOR WAY"字段

So i want to access a field from my dynamic fields like for example "COLOR WAY". In my model i want to access the COLOR WAY field on the dynamic field like this way

$material->color_way;

有人可以告诉我该怎么做吗? 对不起,我的英语.

Can anybody show me how to do it? sorry for my English.

推荐答案

如果知道提前只有某些动态字段,则可以选择为其创建访问器方法.例如,您可以将其添加到模型中:

If you know that there will only be certain dynamic fields ahead of time, you could opt to create accessor methods for them. For example, you could add this to your model:

// 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;
}

这将允许您执行以下操作:

This will allow you to do:

$colorWay = $material->color_way;

或者,如果您的dynamic_fields组合不受限制,则可能有很多组合,或者您希望有更大的灵活性来添加和访问它们,则可以覆盖getAttribute Laravel模型类的方法.

Alternatively, if the combinations your dynamic_fields are not limited, there could be a large number of them or you want there to be more flexibility to be able to add more and have them accessible, you could override the getAttribute method of Laravel's model class.

// 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;
}

此方法调用Laravel的getAttribute实现,该实现首先检查您是否定义了实际属性,或者是否为属性定义了访问器(如我的第一个建议),然后检查是否存在具有该名称的方法在基础模型类上,然后如果定义了关系,则最后尝试加载关系.

This approach calls Laravel's implementation of getAttribute which first checks if you have an actual attribute defined, or if you have an accessor defined for the attribute (like in my first suggestion), then checks if a method exists with that name on the base model class and then finally attempts to load a relation if you have one defined.

当每种方法都失败时(返回null),我们然后检查模型中是否存在dynamic_fields属性.如果存在,我们将遍历每个动态字段(假设您将dynamic_fields强制转换为array),然后将定义的动态字段的名称转换为小写并用下划线替换空格.然后,我们最终检查一下我们刚派生的名称是否与提供的键匹配,如果匹配,则返回该值.如果没有,则将返回原始的$attribute,即null.

When each of those approaches fails (null is returned), we then check to see if there's a dynamic_fields attribute in the model. If there is, we loop through each of the dynamic fields (assuming your dynamic_fields is cast as an array), we then convert the name of the defined dynamic field to lowercase and replace spaces with underscores. We then finally check to see if the name we have just derived matches the key provided and if it does, we return the value. If it doesn't, the original $attribute will be returned, which will be null.

这将使您能够获取任何动态字段,就像它们在类中被定义为属性一样.

This would allow you to get any of your dynamic fields as if they were defined as attributes in the class.

$colorWay = $material->color_way;
$description = $material->description;
$refNum = $material->ref_num;

请注意::我尚未测试此代码,可能存在一两个问题.尝试一下,看看它是否对您有用.另外请注意,这仅适用于获取动态字段,设置它们将需要覆盖另一种方法.

Please note: I have not tested this code, there could well be an issue or two present. Give it a try and see if it works for you. Also note that this will only work for getting dynamic fields, setting them will require overriding another method.

这篇关于Laravel模型动态属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆