Add a custom attribute to a Laravel / Eloquent model on load?-open source projects laravel/laravel

coatesap

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.”

The best solution that I’ve found so far 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);    
    }

}

Update October 2013: As per trm42’s answer, as of Laravel v4.08, there is now an easier way to achieve this:

class Book extends Eloquent {

    protected $table = 'books';
    protected $appends = array('upper');

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

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.