Eloquent Accessors and Mutators: Three Examples (Laravel 9+ vs Laravel 8)

While working with models - we often need to do something with the data before/after saving it in the database: change the format, trim whitespaces, trim HTML tags, and so on.

For that, we can use Accessors and Mutators.

This can be achieved in two different syntax ways, due to changes that were made since Laravel 9. Let's take a look at three different real-life examples:

  • Example for only getting the data
  • Example for only setting the data
  • Example for both getting/setting the data

Example 1. Only getting the data

In this example, we have the most common scenario where there are two fields in the database - first_name and last_name, and we have to combine them, like $user->full_name:

Laravel 9+ Code

app/Models/User.php:

use Illuminate\Database\Eloquent\Casts\Attribute;
 
// ...
 
public function fullName(): Attribute
{
return new Attribute(
get: fn () => $this->first_name .' ' . $this->last_name
);
}

Laravel 8 Code

app/Models/User.php:

public function getFullNameAttribute(): string
{
return $this->first_name .' ' . $this->last_name;;
}

As you can see, Laravel 9 has a new class called Attribute which is used to define the Accessor.

Notice that the method name is camelCase (fullName) and the attribute itself is snake_case (full_name).


Example 2. Only Saving the data

For this example, we will take the assumption that users can enter HTML content, and we want to allow specific HTML tags, such as <a/><p/>, to be saved in the database. We will use the strip_tags function to remove all other tags:

Laravel 9+ Code

app/Models/Post.php:

use Illuminate\Database\Eloquent\Casts\Attribute;
 
// ...
 
public function description(): Attribute
{
return new Attribute(
set: fn($value) => strip_tags($value, '<a><p>')
);
}

Laravel 8 Code

app/Models/Post.php:

public function setDescriptionAttribute($value): void
{
$this->attributes['description'] = strip_tags($value, '<a><p>');
}

Example 3. Getting and Saving the data

In this example, we will both get and save the column. We will use a very simplified currency converter to store the input amount as int in the database and return it as float to the UI:

Laravel 9+ Code

app/Models/Product.php:

use Illuminate\Database\Eloquent\Casts\Attribute;
 
// ...
 
public function price(): Attribute
{
return new Attribute(
get: fn($value) => $value / 100,
set: fn($value) => $value * 100
);
}

Laravel 8 Code

app/Models/Product.php:

public function getPriceAttribute($value): int
{
return $value / 100;
}
 
public function setPriceAttribute($value): void
{
$this->attributes['price'] = $value * 100;
}

With both getter/setter, it becomes more obvious that we are writing way more code in the old Laravel 8 way to do exactly the same as we would do in Laravel 9 or 10.

avatar
Enrique De Jesus Robledo Camacho

How to skip the accesor?, I mean how to get the original value

avatar

You may name the accessor/mutator differently, like getFormattedPriceAttribute, if you want to also work with original field value.

avatar
Enrique De Jesus Robledo Camacho

Thanks, I also found this other Laravel function, "getRawOriginal()" https://laravel.com/api/8.x/Illuminate/Database/Eloquent/Model.html#method_getRawOriginal

Like our articles?

Become a Premium Member for $129/year or $29/month
What else you will get:
  • 52 courses (952 lessons, total 46 h 42 min)
  • 77 long-form tutorials (one new every week)
  • access to project repositories
  • access to private Discord

Recent Premium Tutorials