Attribute Casting with Laravel
When was developing an application that use the MVC pattern, we need define our model, that is the layer that communicate our application with the database.
But sometimes, we need to casting values that received from model. Let me show an example:
You’re creating a model to represent Products, and need of: name, value, state (if it’s available or not) and when will it be available.
Every time that you need create, show or edit a product, need to casting the values. Our idea with this article is it makes your job easier, therefore, what about if we pass this responsibility to our model, so that it makes this automatically?
For this, Laravel has the $casts property. Let’s see how works:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'price' => 'decimal:2',
'status' => 'boolean',
'availability_at' => 'date'
];
}
Using this property, the attributes are casted automatically, and you not will need make this manually. Let’s see a practical example.
You’re create a method to add some days of delay in the availability of a product, for this, hasn’t used a date, only the quantities of days that want to delay.
Without use the $casts, you make something like this:
public function delay(Request $request)
{
$product->availability_at = Carbon::parseFromFormat('Y-m-d', $product->availability_at)->addDays($request->delay_days);
}
Note that we used the Carbon package to make a parse of the date and after add the quantities of days that want to be delayed.
And, if we use $casts, how would it be? Let’s see:
public function delay(Request $request)
{
$product->availability_at = $product->availability_at->addDays($request->delay_days);
}
More simple and cleaner, sure?
The supported cast types are:
integer
, real
, float
, double
, decimal<digits>
, string
, boolean
, object
, array
, collection
, date
, datetime
, timestamp
, encrypted
, encrypted:object
, encrypted:array
, and encrypted:collection
. When casting to decimal
, you must define the number of digits (decimal:2
).
To demonstrate attribute casting, let's cast the is_admin
attribute, which is stored in our database as an integer (0
or 1
) to a boolean value:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'is_admin' => 'boolean',
];
}
Now the is_admin
attribute will always be cast to a boolean when you access it, even if the underlying value is stored in the database as an integer:
$user = App\Models\User::find(1);
if ($user->is_admin) {
//
}
Date Casting
When using the date
or datetime
cast type, you may specify the date's format.
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'created_at' => 'datetime:Y-m-d',
];