我希望能够在Laravel/Eloquent模型加载时添加一个自定义属性/属性,类似于如何使用RedBean的$model->open()方法实现。
例如,目前,在我的控制器中,我有:
public function index()
{
$sessions = EventSession::all();
foreach ($sessions as $i => $session) {
$sessions[$i]->available = $session->getAvailability();
}
return $sessions;
}
这将是很好的能够省略循环,并有'available'属性已经设置和填充。
我尝试使用文档中描述的一些模型事件在对象加载时附加此属性,但到目前为止没有成功。
注:
'available'不是底层表中的字段。
$sessions作为API的一部分作为JSON对象返回,因此在模板中调用像$session->available()这样的东西是不可取的
在我的订阅模型中,我需要知道订阅是否暂停。
我是这样做的
public function getIsPausedAttribute() {
$isPaused = false;
if (!$this->is_active) {
$isPaused = true;
}
}
然后在视图模板中,我可以使用
$subscription->is_paused获取结果。
getIsPausedAttribute是设置自定义属性的格式,
并使用is_paused在视图中获取或使用该属性。
这个问题是由于Model的toArray()方法忽略了与底层表中的列不直接相关的任何访问器。
正如Taylor Otwell在这里提到的,“这是有意为之,而且是出于性能考虑。”然而,有一个简单的方法来实现这一点:
class EventSession extends Eloquent {
protected $table = 'sessions';
protected $appends = array('availability');
public function getAvailabilityAttribute()
{
return $this->calculateAvailability();
}
}
$ appendds属性中列出的任何属性都将自动包含在模型的数组或JSON形式中,前提是您已经添加了适当的访问器。
旧答案(Laravel版本< 4.08):
我发现的最好的解决方案是重写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);
}
}