Динамический аксессор / свойства в Larvel 5.8 - PullRequest
0 голосов
/ 08 мая 2019

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

Мне удалось справиться с этим, написав метод доступа для каждого отдельного атрибута, но я считаю его излишним и безобразным. Я уверен, что это можно сделать более эффективно.

class MyModel extends Model
{
    public function getTitleAttribute()
    {
        return $this->loadAttributeFromConfig('title');
    }

    public function getSubtitleAttribute()
    {
        return $this->loadAttributeFromConfig('subtitle');
    }

    public function getTagAttribute()
    {
        return $this->loadAttributeFromConfig('tag');
    }

    public function getIconCssClassAttribute()
    {
        return $this->loadAttributeFromConfig('iconCssClass');
    }

    public function getBoxCssClassAttribute()
    {
        return $this->loadAttributeFromConfig('boxCssClass');
    }

    public function getBulletsAttribute()
    {
        return $this->loadAttributeFromConfig('bullets');
    }

    protected function loadAttributeFromConfig($attribute)
    {
        return config('myConfigAttributes.' . $this->name . '.' . $attribute);
    }
}

$myModel->append(['title', 'subtitle', 'tag', 'iconCssClass', 'boxCssClass', 'bullets']);

Мое решение работает, но я считаю его безобразным.

1 Ответ

1 голос
/ 08 мая 2019

Этого можно добиться довольно легко, используя магический метод __get.Вы можете переопределить его в базовом классе модели, который вы наследуете, или создать черту, например, так:

trait ConfigAttributes
{
    /**
     * @param string $key
     *
     * @return mixed
     * @throws \Exception
     */
    public function __get($key)
    {
        // Make sure the required configuration property is defined on the parent class
        if (!property_exists($this, 'configAttributes')) {
            throw new Exception('The $configAttributes property should be defined on your model class');
        }

        if (in_array($key, $this->configAttributes)) {
            return $key;
        }

        return parent::__get($key);
    }

    /**
     * @return array
     */
    public function toArray()
    {
        // We need to override this method because we need to manually append the
        // attributes when serializing, since we're not using Eloquent's accessors

        $data = collect($this->configAttributes)->flip()->map(function ($v, $key) {
            return $this->loadAttributeFromConfig($key);
        });

        return array_merge(parent::toArray(), $data->toArray());
    }

    /**
     * @param string $attribute
     *
     * @return mixed
     */
    protected function loadAttributeFromConfig($attribute)
    {
        return config('myConfigAttributes.' . $this->name . '.' . $attribute);
    }
}

Затем в классе модели просто импортируйте черту и укажите свои настраиваемые поля:

class MyModel extends Model
{
    use ConfigAttributes;

    protected $configAttributes = [
        'title',
        'subtitle',
        'tag',
        'iconCssClass',
        'boxCssClass',
        'bullets'
    ];
}

Предостережение: будьте осторожны при переопределении магических методов в классах, определенных Laravel, потому что Laravel интенсивно их использует, и если вы неосторожны, вы рискуете нарушить другие функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...