Evaluation of PHP for immutable objects

Published Jan 19, 2023 on PHP by Al Imran Ahmed

You might already know about the new changes of PHP 8.1 and 8.2. In these versions PHP introduced readonly property and readonly class. Now the question is why do we need readonly? What was the problem without readonly? Let's see the evolution of code to write a class for immutable object.

Before PHP 8.1

Let's write a class for data transfer object(DTO) in a PHP version before 8.1, I don't have readonly.

class UserData {

    public function __construct(
        private string $name,
        private string $email,
        private DateTime $dob
    ) {}
    public function getName(): string {
        return $this->name;
    public function getEmail(): string {
        return $this->email;
    public function getDob(): DateTime {
        return $this->dob;

In the above code, UserData is a Data Transfer Object(DTO) class which means we only need this class to transfer data from one layer of the application to another layer. This is why, once we create an object of UserData class we don't need to change any property of that object. In other words, the object of this class is immutable. To achieve this immutability what have we done? We make the properties of the class private and then we wrote getter method for every property. Now, if someone creates an instance of UserData class, they can get the name property using the public method getName(). But, as the property is private and there is no setter method in the class, it's not possible to change the value of any property of that object. For example:

$userData = new UserData("Al Imran Ahmed", "imran@example.com", "2000-01-01");

print($userData->getName()); // POSSIBLE as getName() is a public method 

$userData->name = "Nure Alam"; // NOT POSSIBLE as $name is a private property

After PHP 8.1

In PHP 8.1 we got a new feature! We can define a property as readonly. By using this readonly keyword we can achieve the same immutability as we have seen above with much less code. Here is how:

class UserData {

    public function __construct(
        public readonly string $name,
        public readonly string $email,
        public readonly DateTime $dob
    ) {}

Our new `UserData` class is lot smaller but behaves similar way. As our properties are now public, so we can get them directly without using any method. On the other hand, we can modify the value of the property because of this newly introduced `readonly` keyword. Isn't it awesome?
$userData = new UserData("Al Imran Ahmed", "imran@example.com", "2000-01-01");

print($userData->name); // POSSIBLE as $name is a public property 

$userData->name = "Nure Alam"; // NOT POSSIBLE as $name is a readonly property

There is one difference though, in our previous UserData class, as the property was private and only accessible via public getter methods. We had some extra control while returning the data. For instance, we could have format the dob before returning is not the case in our 2nd UserData class.

After PHP 8.2

Now, there is more improvement in this same feature in 8.2! As you can see, in our case all the properties of UserData are readonly. So, we need to write the keyword readonly as may time as our total property. What if we declare the whole class as readonly? Yes! this is what introduced in 8.2. You can get exact same behaviour as the last class using the following code:

class readonly UserData {

    public function __construct(
        public string $name,
        public string $email,
        public DateTime $dob
    ) {}

No more, unnecessary verbose code, no more repeated readonly and your object is still immutable? Isn't PHP getting Awesome?

More articles on PHP


No noise, unsubscribe anytime!
© 2024 Al Imran Ahmed
Proudly build with: Larablog