在加载时将自定义属性添加到Laravel / Eloquent模型?
我希望能够在加载时为Laravel / Eloquent模型添加一个自定义属性/属性,类似于RedBean的 $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)在这里提到,“这是故意的,是出于性能的原因。” 但是有一个简单的方法来实现这一点:
class EventSession extends Eloquent { protected $table = 'sessions'; protected $appends = array('availability'); public function getAvailabilityAttribute() { return $this->calculateAvailability(); } }
在$ appends属性中列出的任何属性都会自动包含在模型的数组或JSONforms中,前提是您已经添加了相应的访问器。
旧回答(Laravel版本<4.08):
我find的最好的解决scheme是重写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); } }
Laravel Eloquent文档页面上的最后一件事是:
protected $appends = array('is_admin');
可以自动使用它来为模型添加新的访问器,而不需要像修改方法::toArray()
那样进行额外的工作。
只需创buildgetFooBarAttribute(...)
存取器并将foo_bar
添加到$appends
getFooBarAttribute(...)
数组中即可。
如果您将getAvailability()
方法重命名为getAvailableAttribute()
您的方法将成为访问器 ,您将可以直接在模型上使用->available
直接读取该方法。
文档: https : //laravel.com/docs/5.4/eloquent-mutators#accessors-and-mutators
编辑:由于你的属性是“虚拟的”,它不是默认包含在你的对象的JSON表示。
但是我发现: 当 – > toJson()被调用时,自定义模型访问器没有被处理?
为了强制你的属性在数组中返回,把它作为一个键添加到$ attributes数组中。
class User extends Eloquent { protected $attributes = array( 'ZipCode' => '', ); public function getZipCodeAttribute() { return .... } }
我没有对它进行testing,但对于您在当前的设置中进行尝试应该是相当微不足道的。
您可以使用Model中的setAttribute
函数来添加自定义属性
我有类似的东西:我的模型中有一个属性图片,它包含了文件在存储文件夹中的位置。 该图像必须返回base64编码
//Add extra attribute protected $attributes = ['pictureData']; //Make it available in the json response protected $appends = ['pictureData']; //implement the attribute public function getPictureDataAttribute() { $file = Storage::get($this->picture); $type = Storage::mimeType($this->picture); return "data:" . $type . ";base64," . base64_encode($file); }
在我的情况下,创build一个空列,并设置其访问器工作正常。 我的访问者从dob栏填充用户的年龄。 toArray()函数也起作用。
public function getAgeAttribute() { return Carbon::createFromFormat('Ym-d', $this->attributes['dateofbirth'])->age; }
在我的订阅模式中,我需要知道订阅是否已暂停。 这里是我如何做它public function getIsPausedAttribute() { $isPaused = false; if (!$this->is_active) { $isPaused = true; } }
public function getIsPausedAttribute() { $isPaused = false; if (!$this->is_active) { $isPaused = true; } }
那么在视图模板中,我可以使用$subscription->is_paused
来得到结果。
getIsPausedAttribute
是设置自定义属性的格式,
并使用is_paused
来获取或使用您的视图中的属性。