我希望能够在加载 Laravel/Eloquent 模型时为其添加自定义属性/属性,类似于使用 RedBean's $model->open()
方法可以实现的方式。
例如,目前,在我的控制器中,我有:
public function index()
{
$sessions = EventSession::all();
foreach ($sessions as $i => $session) {
$sessions[$i]->available = $session->getAvailability();
}
return $sessions;
}
如果能够省略循环并且已经设置并填充了“可用”属性,那就太好了。
我尝试使用文档中描述的一些模型事件在对象加载时附加此属性,但到目前为止没有成功。
笔记:
“可用”不是基础表中的字段。
$sessions 作为 API 的一部分作为 JSON 对象返回,因此不能在模板中调用类似 $session->available() 的东西
该问题是由于 Model
的 toArray()
方法忽略了与基础表中的列不直接相关的任何访问器这一事实引起的。
正如 Taylor Otwell 提到的 here,“这是出于性能原因的故意。”但是,有一种简单的方法可以实现这一点:
class EventSession extends Eloquent {
protected $table = 'sessions';
protected $appends = array('availability');
public function getAvailabilityAttribute()
{
return $this->calculateAvailability();
}
}
只要您添加了适当的访问器,$appends 属性中列出的任何属性都将自动包含在模型的数组或 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);
}
}
last thing on the Laravel Eloquent doc page 是:
protected $appends = array('is_admin');
这可以自动用于向模型添加新的访问器,而无需像修改 ::toArray()
这样的方法等任何额外工作。
只需创建 getFooBarAttribute(...)
访问器并将 foo_bar
添加到 $appends
数组。
toArray
方法。
如果您将 getAvailability()
方法重命名为 getAvailableAttribute()
,您的方法将成为 访问器,您将能够直接在模型上使用 ->available
读取它。
文档:https://laravel.com/docs/5.4/eloquent-mutators#accessors-and-mutators
编辑:由于您的属性是“虚拟的”,因此默认情况下它不包含在对象的 JSON 表示中。
但我发现了这个:Custom model accessors not processed when ->toJson() called?
为了强制在数组中返回您的属性,请将其作为键添加到 $attributes 数组中。
class User extends Eloquent {
protected $attributes = array(
'ZipCode' => '',
);
public function getZipCodeAttribute()
{
return ....
}
}
我没有对其进行测试,但在您当前的设置中尝试应该很简单。
->available
在 $session
对象上可用一样有效,但由于 $sessions
直接转换为 JSON 字符串(它是 API 的一部分),因此没有机会使用它。
EventSession::all()
从 API 返回一个 JSON 对象,那么您并没有真正使用 Laravel 模型,对吧?抱歉,我对您如何实现模型感到困惑。
class EventSession extends Eloquent
)。 ::all()
只是一个例子。 EventSession::find(170071)
将是另一个。这些在整个 SessionController (SessionController extends \BaseController
) 的各个点被调用,这些点将通过诸如“/sessions/170071”之类的 URL 调用。
public $available
),转换对象时也不会显示此属性。
protected $appends = array('is_admin');
)
我有一些类似的东西:我的模型中有一张属性图片,它包含存储文件夹中文件的位置。图像必须以 base64 编码返回
//Add extra attribute
protected $attributes = ['picture_data'];
//Make it available in the json response
protected $appends = ['picture_data'];
//implement the attribute
public function getPictureDataAttribute()
{
$file = Storage::get($this->picture);
$type = Storage::mimeType($this->picture);
return "data:" . $type . ";base64," . base64_encode($file);
}
第 1 步:在 $appends
中定义属性 第 2 步:为该属性定义访问器。
示例:
<?php
...
class Movie extends Model{
protected $appends = ['cover'];
//define accessor
public function getCoverAttribute()
{
return json_decode($this->InJson)->cover;
}
您可以在模型中使用 setAttribute
函数来添加自定义属性
假设您的用户表中有 2 列名为 first_name 和 last_name,并且您想要检索全名。您可以使用以下代码实现:
class User extends Eloquent {
public function getFullNameAttribute()
{
return $this->first_name.' '.$this->last_name;
}
}
现在你可以得到全名:
$user = User::find(1);
$user->full_name;
在我的订阅模型中,我需要知道订阅是否已暂停。我是这样做的
public function getIsPausedAttribute() {
$isPaused = false;
if (!$this->is_active) {
$isPaused = true;
}
}
然后在视图模板中,我可以使用 $subscription->is_paused
来获取结果。
getIsPausedAttribute
是设置自定义属性的格式,
并使用 is_paused
获取或使用视图中的属性。
就我而言,创建一个空列并设置其访问器工作正常。我的访问者从 dob 列填充用户的年龄。 toArray() 函数也有效。
public function getAgeAttribute()
{
return Carbon::createFromFormat('Y-m-d', $this->attributes['dateofbirth'])->age;
}
不定期副业成功案例分享
protected $hidden = []
添加要排除的列/访问器。