Динамический атрибут модели Laravel - PullRequest
0 голосов
/ 28 сентября 2018

Я хотел бы спросить, как создать динамический атрибут в классе модели.Предположим, у меня есть структура таблицы, как показано ниже.

   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;

Кто-нибудь может показать мне, как это сделать?извините за мой английский.

Ответы [ 2 ]

0 голосов
/ 28 сентября 2018

Если вы знаете, что заранее будут только определенные динамические поля, вы можете создать методы доступа для них.Например, вы можете добавить это к вашей модели:

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

В качестве альтернативы, если комбинации ваших 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;
}

Этот подходвызывает реализацию Laravel getAttribute, которая сначала проверяет, определен ли у вас фактический атрибут или определен метод доступа для этого атрибута (как в моем первом предложении), а затем проверяет, существует ли метод с этим именем в классе базовой моделии затем, наконец, пытается загрузить отношение, если оно определено.

Когда каждый из этих подходов дает сбой (возвращается null), мы затем проверяем, есть ли атрибут dynamic_fields в модели.Если есть, мы перебираем каждое из динамических полей (предполагая, что ваш dynamic_fields приведен как array), затем мы конвертируем имя определенного динамического поля в нижний регистр и заменяем пробелы подчеркиванием.Затем мы, наконец, проверяем, соответствует ли только что полученное нами имя указанному ключу, и если это так, мы возвращаем значение.Если этого не произойдет, будет возвращен исходный $attribute, который будет null.

Это позволит вам получить любое из ваших динамических полей, как если бы они были определены как атрибуты в классе.

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

Обратите внимание: Я не проверял этот код, вполне может быть проблема или два присутствующих.Попробуйте и посмотрите, работает ли он для вас.Также обратите внимание, что это будет работать только для получения динамических полей, установка их потребует переопределения другого метода.

0 голосов
/ 28 сентября 2018

Попробуйте использовать этот код в вашей модели:

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