Laravel Datetime to Carbon Automatically: $dates or $casts

Tutorial last revisioned on March 15, 2024 with Laravel 11

In Laravel, there's a convenient way to transform date/time DB fields to Carbon objects automatically. In fact, there are two ways, let me tell you about both.

Inconvenience: With No Casting

Imagine you have a DB field projects.activated_at with values in the DB like "2022-10-05" or "2021-12-23", so a typical YYYY-MM-DD.

What if you want to show them in another format to users, like "m/d/Y"?

You need to convert them every time, right? And Carbon library would help, something like this:

Carbon::createFromFormat('Y-m-d', $project->activated_at)
->format('m/d/Y');

So, you need to create a Carbon object yourself, and then you can convert it to whatever you want.

Every time in every place where you want to show that value.

Wouldn't it be cool to have something like this?

$project->activated_at->format('m/d/Y')?

So, meet Eloquent $casts and $dates.


$casts and $dates Properties

For long years in Laravel, there has been a property that you can define on Eloquent models, which fields should be auto-transformed into Carbon objects:

class Project extends Model {
 
protected $dates = [
'activated_at',
'deactivated_at',
// ...
];
 
}

And then, everywhere you use this value, in Blade or elsewhere, you get a Carbon object and can use it like in the example above: $project->activated_at->format('m/d/Y')

But a bit later, Laravel introduced a more global concept of Casting, auto-transforming any field to any of the available types, and date/time became just one single example of a broader casting topic.

From then, the officially recommended behavior became to auto-Carbon the dates with $casts property, instead of the older $dates:

class Project extends Model {
 
protected $casts = [
'activated_at' => 'date',
'deactivated_at' => 'date',
];
 
}

Now, the new casting property comes with an additional benefit: you can also provide the format inside the property, like this:

protected $casts = [
'activated_at' => 'date:m/d/Y',
'deactivated_at' => 'date:m/d/Y',
];

It will not auto-transform the $project->activated_at to the correct format when you access it, but it will do it when you use ->toArray() or ->toJSON() methods on the model.

$project->activated_at;
// Value: Illuminate\Support\Carbon @1664928000 {#5836
// date: 2022-10-05 00:00:00.0 UTC (+00:00),
// }
 
$project->toArray()['activated_at'];
// Value: 05/10/2022

Since Laravel 11 casts are defined in the casts() method instead of property.

protected function casts(): array
{
return [
'activated_at' => 'date:m/d/Y',
'deactivated_at' => 'date:m/d/Y',
];
}

You can still define casts in a property as it is backward compatible. When an attribute is defined on the property and method, the method one takes priority.

You can read more about date casting in the official docs.


You might also be interested in our PREMIUM course on Dates for Multiple Timezones

avatar

Great article.

I like to read articles about simple stuff instead of videos, easier to resume or see code whenever needed.

👍 10
avatar

Thank you so much for this one. I think I like reading now than watching video haha

avatar

Thank you

Like our articles?

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

Recent New Courses