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.
How to skip the accesor?, I mean how to get the original value
You may name the accessor/mutator differently, like
getFormattedPriceAttribute
, if you want to also work with original field value.Thanks, I also found this other Laravel function, "getRawOriginal()" https://laravel.com/api/8.x/Illuminate/Database/Eloquent/Model.html#method_getRawOriginal