Add a custom attribute to a Laravel / Eloquent model on load?
The problem is caused by the fact that the Model
's toArray()
method ignores any accessors which do not directly relate to a column in the underlying table.
As Taylor Otwell mentioned here, "This is intentional and for performance reasons." However there is an easy way to achieve this:
class EventSession extends Eloquent { protected $table = 'sessions'; protected $appends = array('availability'); public function getAvailabilityAttribute() { return $this->calculateAvailability(); }}
Any attributes listed in the $appends property will automatically be included in the array or JSON form of the model, provided that you've added the appropriate accessor.
Old answer (for Laravel versions < 4.08):
The best solution that I've found is to override the toArray()
method and either explicity set the attribute:
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); }}
or, if you have lots of custom accessors, loop through them all and apply them:
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); }}
The last thing on the Laravel Eloquent doc page is:
protected $appends = array('is_admin');
That can be used automatically to add new accessors to the model without any additional work like modifying methods like ::toArray()
.
Just create getFooBarAttribute(...)
accessor and add the foo_bar
to $appends
array.
If you rename your getAvailability()
method to getAvailableAttribute()
your method becomes an accessor and you'll be able to read it using ->available
straight on your model.
Docs: https://laravel.com/docs/5.4/eloquent-mutators#accessors-and-mutators
EDIT: Since your attribute is "virtual", it is not included by default in the JSON representation of your object.
But I found this: Custom model accessors not processed when ->toJson() called?
In order to force your attribute to be returned in the array, add it as a key to the $attributes array.
class User extends Eloquent { protected $attributes = array( 'ZipCode' => '', ); public function getZipCodeAttribute() { return .... }}
I didn't test it, but should be pretty trivial for you to try in your current setup.