在加载时向 Laravel / Eloquent 模型添加自定义属性?

2022-08-30 06:08:21

我希望能够在加载时向Laravel/Eloquent模型添加自定义特性/属性,类似于RedBean方法的实现方式。$model->open()

例如,目前,在我的控制器中,我有:

public function index()
{
    $sessions = EventSession::all();
    foreach ($sessions as $i => $session) {
        $sessions[$i]->available = $session->getAvailability();
    }
    return $sessions;
}

如果能够省略循环并设置并填充“available”属性,那就太好了。

我尝试使用文档中描述的一些模型事件在对象加载时附加此属性,但到目前为止尚未成功。

笔记:

  • “可用”不是基础表中的字段。
  • $sessions作为 API 的一部分作为 JSON 对象返回,因此调用类似模板的内容不是一个选项$session->available()

答案 1

这个问题是由以下事实引起的:'s 方法忽略了任何与基础表中的列没有直接关系的访问器。ModeltoArray()

正如泰勒·奥特韦尔(Taylor Otwell)在这里提到的那样,“这是故意的,也是出于性能原因。但是,有一种简单的方法可以实现这一点:

class EventSession extends Eloquent {

    protected $table = 'sessions';
    protected $appends = array('availability');

    public function getAvailabilityAttribute()
    {
        return $this->calculateAvailability();  
    }
}

$appends属性中列出的任何属性都将自动包含在模型的数组或 JSON 表单中,前提是您已添加相应的访问器。

旧答案(对于 4.08 < Laravel 版本):

我发现的最佳解决方案是重写该方法并显式设置属性:toArray()

class Book extends Eloquent {

    protected $table = 'books';

    public function toArray()
    {
        $array = parent::toArray();
        $array['upper'] = $this->upper;
        return $array;
    }

    public function getUpperAttribute()
    {
        return strtoupper($this->title);    
    }

}

或者,如果您有很多自定义访问器,请遍历所有访问器并应用它们:

class Book extends Eloquent {

    protected $table = 'books';

    public function toArray()
    {
        $array = parent::toArray();
        foreach ($this->getMutatedAttributes() as $key)
        {
            if ( ! array_key_exists($key, $array)) {
                $array[$key] = $this->{$key};   
            }
        }
        return $array;
    }

    public function getUpperAttribute()
    {
        return strtoupper($this->title);    
    }

}

答案 2

Laravel Eloquent doc页面上的最后一件事是

protected $appends = array('is_admin');

这可以自动用于向模型添加新的访问器,而无需任何额外的工作,例如修改诸如.::toArray()

只需创建访问器并添加到数组即可。getFooBarAttribute(...)foo_bar$appends


推荐