[英]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.