Laravel模型动态属性

时间:2018-09-28 08:29:46

标签: php laravel dynamic attributes field

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

   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结构的示例。

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

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

$material->color_way;

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

3 个答案:

答案 0 :(得分:1)

尝试在模型中使用此代码:

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

答案 1 :(得分:0)

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

this.props.switchLanguage

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

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

或者,如果您的$colorWay = $material->color_way; 的组合不受限制,则可能有很多组合,或者您希望有更大的灵活性来添加更多并可以访问它们,则可以覆盖{ {1}}是Laravel模型类的方法。

dynamic_fields

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

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

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

$attribute

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

答案 2 :(得分:0)

在此示例中,您可以从动态模型获得动态列。以及它的模型关系

1)首先,您必须在Model中定义一个表Scope。

  private  $dynamicTable='';

  public function scopeDefineTable($query,$tableName)
{
    if( $tableName )
    {
        $this->dynamicTable= $tableName;
    }
    else
    {
        $this->dynamicTable= "deviceLogs_".date('n')."_".date('Y');
    }
    $query->from( $this->dynamicTable );

   $this->table=$this->dynamicTable; # give dynamic table nam to this model.
}


  public function  scopeCustomSelect( $query ,$items=[])
{
    $stu_class_col=['id as stu_class_id','std_id']; // Required else retional model will not retun data. here id and std_id is primary key and foreign key.
    $stu_doc_col=['id as stu_doc_id','std_id'];// Required else retional model will not retun data. here id and std_id is primary key and foreign key.

    foreach ( $items as $col)
    {
        if(  Schema::hasColumn('student_information', $col ))
        {
          $stu_info_col[]= $col ;
        }
        elseif (  Schema::hasColumn('student_class',$col))
        {
            $stu_class_col[]= $col ;
        }
        elseif (  Schema::hasColumn('student_image',$col))
        {
            $stu_doc_col[]= $col ;
        }
    }

   // converting array to string for bind column into with relation...
    $stu_class_col_string =  implode(',',$stu_class_col);
    $stu_doc_col_string =  implode(',',$stu_doc_col); 

    return $colQuery = $query->select($stu_info_col)
                    ->with(["student_class:$stu_class_col_string", "studentImage:$stu_doc_col_string"]);
}

使用此方法,您也可以从Rational Model获取数据...

来自控制器

    $studentInfo =  Student::whereHas("student_class",function($q) use($req){
                                   $q->where("std_session",$req->session_code);
                                   $q ->where("std_class",$req->class_code);
                                   $q ->where("std_section",$req->std_section); })
                           ->customSelect($fields['dataList'])
                           ->get();



here I am not using dynamic Model Scope. only Dynamic SustomSelect scope..