w3resource

Laravel (5.7) Eloquent Mutators

Introduction

Mutators and accessors allows you to format Eloquent attribute values when you retrieve or set them on model instances. For instance, when you want to use the laravel encrypter to encrypt a value while it is stored in the database, and then decrypt the attribute automatically when you access it on an Eloquent Model.

Aside custom mutators and accessors, Eloquent can also cast date fields to Carbon instances automatically or cast text fields to JSON.

Accessors & Mutators

Defining An Accessor

If you want to define an accessor, you should create a getFooAttribute method on your model where Foo is the "studly" cased name of the column you wish to access. In the example below, we will define an accessor for the first_name attribute. The accessor is automatically called by Eloquent when attempting to retrieve the value of the first_name attribute:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    /**
     * Get the first name of the user.
     *
     * @param  string  $value
     * @return string
     */
    public function getFirstNameAttribute($value)
    {
        return ucfirst($value);
    }
}

As seen above, the original value of the column will be passed to the accessor, this allows you to manipulate and return the value. For you to access the value of the accessor, you can access the first_name attribute on a model instance:

$user = App\User::find(1);
$firstName = $user->first_name;

You can also return new, computed values from existing attributes using accessors:

/**
 * Get the full name of the user.
 *
 * @return string
 */
public function getFullNameAttribute()
{
    return "{$this->first_name} {$this->last_name}";
}

Defining A Mutator

If you want to define a mutator, you should define a setFooAttribute method on your model where Foo is the "studly" cased name of the column you wish to access. We will define a mutator for the first_name attribute. This mutator is automatically called when we attempt to set the value of the first_name attribute on the model:

<?php
namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Set the first name of the user.
     *
     * @param  string  $value
     * @return void
     */
    public function setFirstNameAttribute($value)
    {
        $this->attributes['first_name'] = strtolower($value);
    }
}

The mutator will receive the value that is set on the attribute, this allows you to manipulate the value and then set the manipulated value on the Eloquent model's internal $attributes property. So, if we attempt to set the first_name attribute to Sally:

$user = App\User::find(1);
$user->first_name = 'Sally';

In this instance, the setFirstNameAttribute function is called with the value Sally. The mutator will thus apply the strtolower function to the name and set the resulting value in the internal $attributes array.

Date Mutators

By default, Eloquent converts the created_at and updated_at columns to instances of Carbon, which will extend the PHP DateTime class and then provides an assortment of helpful methods. You can add additional date attributes by setting the $dates property of your model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The attributes that should be mutated to dates.
     *
     * @var array
     */
    protected $dates = [
        'seen_at',
    ];
}

Whenever a column is considered a date, you can set its value to a UNIX timestamp, date string (Y-m-d), date-time string, or a DateTime / Carbon instance. The date's value is correctly converted and stored in the database:

$user = App\User::find(1);
$user->deleted_at = now();
$user->save();

When you retrieve attributes that are listed in your $dates property, they are automatically cast to Carbon instances, this allows you to use any of Carbon's methods on your attributes:

$user = App\User::find(1);
return $user->deleted_at->getTimestamp();

Date Formats

By default, timestamps will be formatted as 'Y-m-d H:i:s'. If there is need to customize the timestamp format, then set the $dateFormat property on your model. This property will determine how date attributes are stored in the database, as well as their format when the model will be serialized to an array or JSON:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The storage format of the model's date columns.
     *
     * @var string
     */
    protected $dateFormat = 'U';
}

Attribute Casting

The $casts property on our model provides a convenient method of converting attributes to common data types. The $casts property should be an array where the key is the name of the attribute that is being cast and the value is the type we wish to cast the column to. The supported cast types are: integer, real, double, float, decimal:<digits>, string, boolean, object, array, collection, date, datetime, and timestamp. When we cast to decimal, we have to define the number of digits, eg. decimal:2

For instance, let us cast the is_admin attribute, stored in our database as an integer (0 or 1) to a boolean value:

<?php

namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    /**
     * The attributes that are cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'is_admin' => 'boolean',
    ];
}

Now the is_admin attribute is always cast to a boolean when you access it, even if the underlying value is stored in the database as an integer:

$user = App\User::find(1);
if ($user->is_admin) {
    //
}

Array & JSON Casting

The array cast type is very useful when you are working with columns that are stored as serialized JSON. For instance, if your database contains a JSON or TEXT field type that has serialized JSON, addition of the array cast to that attribute will automatically deserialize the attribute to a PHP array when you access it on the Eloquent model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'options' => 'array',
    ];
}

when the cast is defined, you can access the options attribute and it is automatically deserialized from JSON into a PHP array. When you set the value of the options attribute, the given array will automatically be serialized back into JSON for storage:

$user = App\User::find(1);
$options = $user->options;
$options['key'] = 'value';
$user->options = $options;
$user->save();

Date Casting

When you are using the date or datetime cast type, you can specify the date's format. This format is used when the model is serialized to an array or JSON:

/**
 * The attributes that should be cast to native types.
 *
 * @var array
 */
protected $casts = [
    'created_at' => 'datetime:Y-m-d',
];


Share this Tutorial / Exercise on : Facebook and Twitter