Создание динамического средства доступа Laravel


У меня есть модель Product, а также модель Attribute. Связь между Product и Attribute - это много ко многим. В моей модели Product я пытаюсь создать динамический способ доступа. Я знаком с функциями доступа и мутаторов Laravel, описанными в документе здесь. Проблема, с которой я сталкиваюсь, заключается в том, что я не хочу создавать средство доступа каждый раз, когда я создаю атрибут продукта.

Например, у продукта может быть атрибут цвета, который можно настроить следующим образом:

/**
 * Get the product's color.
 *
 * @param  string  $value
 * @return string
 */
public function getColorAttribute($value)
{
    foreach ($this->productAttributes as $attribute) {
        if ($attribute->code === 'color') {
            return $attribute->pivot->value;
        }
    }

    return null;
}

В затем можно было бы получить доступ к цвету продукта следующим образом $product->color. Если бы я хотел добавить атрибут size к продукту, мне нужно было бы настроить другой способ доступа к модели Product, чтобы я мог получить к нему доступ вот так $product->size.

Есть ли способ настроить один "динамический" способ доступа для обработки всех моих атрибутов при доступе в качестве свойства?

Нужно ли мне переопределять функции доступа Laravel своими собственными?

Author: Denis Priebe, 2017-11-22

3 answers

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

Может быть, у вас может быть функция:

public function getProductAttr($name)
{
    foreach ($this->productAttributes as $attribute) {
        if ($attribute->code === $name) {
            return $attribute->pivot->value;
        }
    }

    return null;
}

И назовем это так:

$model->getProductAttr('color');
 3
Author: Laraleg, 2017-11-22 19:13:46

Переопределить магический метод - __метод get().

Попробуйте это.

public function __get($key)
{
    foreach ($this->productAttributes as $attribute) {
        if ($attribute->code === $key) {
            return $attribute->pivot->value;
        }
    }

    return parent::__get($key);
}
 2
Author: Abid Raza, 2017-11-22 16:19:36

Я думаю, что, вероятно, ответ Олег Шовкун правильный, но если бы вы хотели использовать обозначение атрибута модели, вы могли бы ввести требуемый аргумент в модель через переменную класса.

class YourModel extends Model{

  public $code;

  public function getProductAttribute()
  {
    //a more eloquent way to get the required attribute
    if($attribute = $this->productAttributes->filter(function($attribute){
       return $attribute->code = $this->code;
    })->first()){
        return $attribute->pivot->value;
    }

    return null;
  }
}

Затем сделайте

$model->code = 'color';
echo $model->product;

Но это немного длинно и бессмысленно

 0
Author: Mike Miller, 2017-11-23 15:21:55