动态附件/属性在Larvel 5.8中

时间:2019-05-08 14:44:04

标签: php laravel

我正在尝试对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 个答案:

答案 0 :(得分:1)

使用__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大量使用了它们,如果不小心,可能会破坏其他功能。