简体   繁体   English

动态附件/属性在Laravel 5.8中

[英]Dynamic accesor / properties in Laravel 5.8

I'm trying to use dynamic accessor for Laravel model's virtual attributes. 我正在尝试为Laravel模型的虚拟属性使用动态访问器。 Actually I want to handle the situation that if a property doesn't directly exist / doesn't exist in database, load it's value from config file. 实际上,我想处理以下情况:如果属性不直接存在/数据库中不存在,请从配置文件中加载它的值。

I managed to handle it by writing a accessor for each single attribute, but I find it redundant and ugly. 我设法通过为每个单个属性编写一个访问器来处理它,但是我发现它是多余且丑陋的。 I'm sure it can be done more effectively. 我相信它可以更有效地完成。

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']);

My solution works but I consider it ugly. 我的解决方案有效,但我认为它很丑。

This can actually be achieved rather easily using the __get magic method. 实际上,可以使用__get magic方法轻松实现此__get You can override it on a base model class that you inherit or create a trait like so: 您可以在继承的基本模型类上重写它,或创建一个特征,如下所示:

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

Then in you model class just import the trait and specify your custom fields: 然后在模型类中,只需导入特征并指定您的自定义字段:

class MyModel extends Model
{
    use ConfigAttributes;

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

Word of caution: be careful when overriding magic methods on classes defined by Laravel, because Laravel makes heavy use of them and if you're not careful you risk breaking other functionality. 警告:在Laravel定义的类上覆盖魔术方法时要小心,因为Laravel大量使用了它们,如果不小心就可能会破坏其他功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM