Transform Eloquent Attributes with withCasts()
Sometimes a query returns a calculated value that you want Laravel to treat as a specific data type.
For example, you might retrieve a date through a subquery but want to access it as a Carbon date instead of a plain string.
Rather than adding a permanent cast to your model, Laravel provides withCasts().
Basic Usage
Imagine your User model has a subquery that retrieves the latest login time:
$users = User::query()
->select('users.*')
->selectSub(
Login::select('created_at')
->whereColumn('user_id', 'users.id')
->latest()
->limit(1),
'last_login_at'
)
->withCasts([
'last_login_at' => 'datetime',
])
->get();
Now Laravel casts last_login_at to a date-time value for these query results.
Access the Casted Value
foreach ($users as $user) {
if ($user->last_login_at) {
echo $user->last_login_at->format('d M Y H:i');
}
}
Because the attribute is cast to datetime, you can use Carbon's date-formatting methods.
Why Not Add It to $casts?
You could define the cast permanently on the model:
protected function casts(): array
{
return [
'last_login_at' => 'datetime',
];
}
But if last_login_at exists only in a particular query, a permanent cast may be unnecessary.
withCasts() keeps that behavior close to the query that needs it.
When Should You Use It?
- Casting subquery results
- Formatting calculated date attributes
- Handling query-specific numeric values
- Applying temporary casts to selected columns