What is the difference between Accessor/Mutators and Casting in laravel?
<?php
...
class User extends Model
{
public function getIsAdminAttribute($value){
return (bool)$value;
}
public function setIsAdminAttribute($value){
$this->attributes['is_admin'] = (bool)$value;
}
}
..
<?php
...
class User extends Model
{
protected $casts = [
'is_admin' => 'boolean',
];
}
I feel like they are both doing the same thing so what is the difference?
CodePudding user response:
An accessor transforms an Eloquent attribute value when it is accessed.
public function getFirstNameAttribute($value)
{
return strtoupper($value);
}
Whenever you fetch a model, the property will be formatted/returned as per the accessor definition. Let's assume that a user's first_name is John
. The above accessor will return the first_name
in uppercase:
$user = User::findOrFail($id);
dd($user->first_name); // Will return 'JOHN' instead of 'John' because accessor
In the opposite way, a mutator will handle the property before being stored in your database
public function setFirstNameAttribute($value)
{
$this->attributes['first_name'] = strtoupper($value);
}
Whenever you save a model, the property will be formatted as per the mutator definition. Let's assume that you pass a user's first_name as John
. The above mutator will transform the first_name
as JOHN
before store:
$user = new User();
$user->first_name = 'John'; // It will be stored as JOHN because mutator
$user->save();
The attribute casting provides functionality similar to accessors and mutators. The main purpose is for using predefined casting methods instead of manually defining your own ones. IE, creating a date Carbon instance from a property:
protected $casts = [
'birthday' => 'date',
];
Instead of
public function getBirthdayAttribute($value)
{
return Carbon::create($value);
}
public function setBirthdayAttribute($value)
{
$this->attributes['birthday'] = Carbon::create($value);
}
You can check docs at https://laravel.com/docs/8.x/eloquent-mutators#attribute-casting
CodePudding user response:
In addition to what Luciano wrote, accessors and mutators can do things that casting cannot. In the example below, we define a is_birthday
attribute.
/**
* @property Carbon date_of_birth
* @property-read boolean is_birthday
*/
class Person extends Model {
public function getIsBirthdayAttribute(){
return $this->attributes['date_of_birth']->isToday();
}
}
These derived attributes can be really helpful to abstract away common access patterns, like getting a full name from first and last names or computing invoice (sub)totals.