CarbonImmutable Class: Why You Would Need It

All of you probably use the Carbon class in Laravel for date/time operations. But have you heard about CarbonImmutable? It may rescue you from one potential bug. Let me explain its use case in this short tutorial.


Let's say we have a variable, which is a carbon instance. It shows 9 am.

$now = now()
= Illuminate\Support\Carbon @1701769227 {#8589
date: 2023-12-05 09:40:27.931975 UTC (+00:00),
}

The now() function is a Carbon\Carbon::now() shorter version.

For example, let's introduce a variable $threeHoursLater.

$threeHoursLater = $now->addHours(3);
= Illuminate\Support\Carbon @1701780027 {#8589
date: 2023-12-05 12:40:27.931975 UTC (+00:00),
}

We can see the result three hours later, at 12 pm.

But now, what if from the original $now you want to create a four hours later. We expect the result to be 13 because 9+4, but we get 16.

$threeHoursLater = $now->addHours(4);
= Illuminate\Support\Carbon @1701794427 {#8589
date: 2023-12-05 16:40:27.931975 UTC (+00:00),
}

It is because of how Carbon works. It not only assigns the value to the new variable but also changes the original object. This means whatever new operation you launch on the same object, it will be from the last change of that object.

That's why there is a separate class called CarbonImmutable. Assigning the now value, you won't see any difference.

$now = Carbon\CarbonImmutable::now();
= Carbon\CarbonImmutable @1701770010 {#8596
date: 2023-12-05 09:53:30.203054 UTC (+00:00),
}

After adding three hours later, we see the same 12 pm result.

$threeHoursLater = $now->addHours(3);
= Carbon\CarbonImmutable @1701780810 {#8590
date: 2023-12-05 12:53:30.203054 UTC (+00:00),
}

But the main difference is setting the third variable after four hours.

$threeHoursLater = $now->addHours(4);
= Carbon\CarbonImmutable @1701784410 {#8586
date: 2023-12-05 13:53:30.203054 UTC (+00:00),
}

Now, we get the expected result. Now, the operation is done from the original $now variable value.

If you want to watch this lesson as a video, there is a YouTube video Carbon VS CarbonImmutable in Laravel: Avoid Potential Errors.

avatar

Or remember always use a ->copy() method.

avatar

That is impossible. Humans do make mistakes and they can be costly :) That's why immutable exists!

avatar

Damn i have to say that is annoying behaviour on laravels side. Why is the immutable class not default? i think i have to change some code in my app.. :/

avatar

because of tradeoff... Immutable will have some extra performance cost..

avatar

Actually this is not a bug or a problem with Laravel or Carbon, this is the default behaviour of PHP Object Oriented Programming.

PHP objects are passed by reference by default. https://www.php.net/manual/en/language.oop5.references.php

In order to have a copy, or new object you use 'clone'.

If you look at the source code for CarbonImmutable object which extends DateTimeImmutable, the additional method clone is used, which creates a new object.

And looking at the class Carbon extends DateTime behave the same as Immutable objects, except they modify itself when modification methods such as DateTime::modify() are called. https://www.php.net/manual/en/class.datetime.php

All by design, not a bug.

avatar

You are correct. But using Carbon instead of CarbonImmutable can definitely cause bugs in your system. So while everything you said is true - there's one crucial aspect - people treat this as a "bug" and google it as such.

In any case, understanding OOP and how things work is mandatory, but this is just something people never think about. Well, unless it's too late!

Like our articles?

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

Recent Premium Tutorials