---
title: "Immutable Carbon in Laravel"
description: "A few Laravel-specific additions to my previous Carbon post: avoiding mutation, switching Laravel to CarbonImmutable globally, and immutable Eloquent casts."
canonical: "https://gummibeer.dev/blog/2023/carbon-techniques-in-laravel"
---

# Immutable Carbon in Laravel

A few Laravel-specific additions to my previous Carbon post: avoiding mutation, switching Laravel to CarbonImmutable globally, and immutable Eloquent casts.

After publishing my [previous post about immutable Carbon](/blog/2023/preserving-date-integrity/), [Alexander von Studnitz](https://twitter.com/jvstudnitz/status/1689309097714225153) pointed out a few Laravel-specific details I had missed.

And one of them changes how I would set this up today: instead of opting into immutable dates at every single callsite, Laravel can use `CarbonImmutable` as its default date implementation throughout the application.

## `->avoidMutation()`

If you receive a `CarbonInterface` somewhere and don't control the concrete instance - package code is the obvious example - `->avoidMutation()` is useful when you want to change the date for a calculation without accidentally changing the original object.

It only clones the instance when it is mutable. If it is immutable already, it simply returns the same instance.

So despite the name, this isn't another way to convert a mutable `Carbon` into `CarbonImmutable`. It just makes sure the following mutation doesn't touch the original object.

## Use `CarbonImmutable` throughout Laravel

This is the more interesting part for me.

Laravel's `DateFactory` allows changing the date class used by the framework. Put this into your `AppServiceProvider->boot()` method:

```php
<?php

namespace App\Providers;

use Carbon\CarbonImmutable;
use Illuminate\Support\DateFactory;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        DateFactory::useClass(CarbonImmutable::class);
    }
}
```

That's it.

After that, `now()` and `today()` return `CarbonImmutable`, but it goes further than those helpers. Calls through Laravel's date factory like `Date::make()` and `Date::parse()` use the configured class as well.

And because Laravel uses the same date factory internally, this also affects Eloquent date casting and `$request->date()` in controllers.

So instead of remembering where I need an immutable date, I can make immutability the default once and keep it consistent across the application.

## What about `immutable_datetime` casts?

Laravel also has an `immutable_datetime` cast:

```php
protected $casts = [
    'published_at' => 'immutable_datetime',
];
```

This is useful if you keep Laravel's default mutable date class and only want specific model attributes to be immutable.

But if you already configured `DateFactory::useClass(CarbonImmutable::class)`, I don't see much value in repeating `immutable_datetime` on every model just to get the same result. The normal `datetime` cast already goes through Laravel's configured date factory.

For me, changing the date factory globally is the cleanest option. One setting, and Laravel consistently gives me immutable dates instead of relying on me to remember the right helper or cast every time.
