Eloquent Date Casting and Mutators
Eloquent Date Casting: Tips & Tricks
Eloquent Date Casting: Tips & Tricks
Tip: Cast to datetime for Carbon Instances
protected $casts = [
'published_at' => 'datetime',
'birthday' => 'date',
];
datetime gives you a full Carbon instance with time. date gives you a Carbon instance at midnight.
Gotcha: $dates is Deprecated
Use $casts instead:
// Old
protected $dates = ['published_at'];
// New
protected $casts = ['published_at' => 'datetime'];
Tip: Carbon Formatting
$post->published_at->format('Y-m-d');
$post->published_at->diffForHumans(); // "2 hours ago"
$post->published_at->toIso8601String();
Gotcha: Timezone Issues
Laravel uses the timezone from config/app.php. If your server is in UTC but your app is in America/New_York, dates can be off.
Tip: Custom Date Format
protected $casts = [
'created_at' => 'datetime:Y-m-d',
];
Gotcha: now() vs today()
now(); // Current date and time
today(); // Today at 00:00:00
Tip: Carbon Macros
Carbon::macro('isWeekend', function () {
return $this->dayOfWeek === 0 || $this->dayOfWeek === 6;
});
$post->published_at->isWeekend();
Gotcha: Date Queries
Post::whereDate('created_at', '2024-01-15')->get(); // Just the date
Post::where('created_at', '>=', '2024-01-15 00:00:00')->get(); // Full datetime
Tip: Use cursor() for Memory-Neutral Iteration
When exporting 100K rows, get() loads everything into memory. cursor() uses yield and keeps memory flat regardless of row count. Perfect for artisan commands.
Tip: whereHas() vs load() — Two Different Things
whereHas() filters the parent query by relationship existence. load() eager-loads relationships AFTER the query. Mixing them up is a common source of logic bugs.
Gotcha: withCount() Adds a Subquery
withCount('comments') runs a correlated subquery on every row. On large tables, this can be slower than a separate query. Profile before relying on it.
Senior Insight
Date casting in Eloquent seems straightforward until you deal with timezones. I've seen apps where created_at was stored in UTC, displayed in EST, and compared in the application's default timezone — producing bugs that only appeared at certain hours. My rule: always store dates in UTC, always convert to the user's timezone at the presentation layer, and never compare dates in PHP without explicitly specifying the timezone. Carbon's setTimezone() is your friend.
Source: Laravel Docs (https://laravel.com/docs/eloquent), Laravel News (https://laravel-news.com/), Freek.dev (https://freek.dev/tags/eloquent)