Please wait

Readonly Properties

Properties are a way to store data within an object. For instance, if we were creating a Car object, we might have properties like color, make, model, and so on. These are pieces of data that describe the car.

Now, some of this data should not be changed after the car is created. For example, the make of the car won't change after the car is manufactured. In PHP, we can make such properties "readonly". A "readonly" property is a property that can be set only once when the object is first created and cannot be changed afterwards.

This is useful because it helps prevent accidental modifications to these properties. For instance, if you accidentally tried to change the "make" of the car after it was created, PHP would give you an error message, saving you from a potentially costly mistake.

Defining readonly properties

A readonly property can be defined by adding the readonly keyword after a public access modifier. Here is an example:

class Car {
  public readonly string $make;
 
  public function __construct(string $make) {
    $this->make = $make;
  }
}

In this example, the $make property of the Car class is defined as "readonly". This means that once a Car object is created and its $make is set, it cannot be changed. Attempting to change it, as the last line of the code does, will cause an error.

Alternatively, we can use constructor property promotion like so:

class Car {
  public function __construct(public readonly string $make) {
  }
}

We can read from this property like any other property:

$myCar = new Car("Toyota");
echo $myCar->make;  // This will output "Toyota"

However, if attempt to access this property like in this example:

$myCar->make = "Honda";  // This will cause an error, as "make" is readonly

PHP throws a fatal error:

Fatal error: Uncaught Error: Cannot modify readonly property Car::$make

Using a method to initialize a property

Aside from initializing the property from its definition or construct method, you can define a method to set the property. This is assuming you haven't assigned a default value. Let's say you wanted to set the $make property's value at a later point.

It's perfectly fine to have a readonly property uninitialized. You can always define a custom method to perform this task.

class Car {
  public readonly string $make;
 
  public function setMake(string $make) {
    $this->make = $make;
  }
}

We can instantiate the class and call the method to set the property.

$car = new Car();
$car->setMake("Honda");

This works without a problem. However, if we were to attempt to call the setMake() method a second time, we'll be given an error. After the property has been given a value, PHP throws an error.

Typed properties

Unlike regular properties, you must always assign a type to a readonly property. If you don't, PHP will throw an error. Take the following:

class Car {
  public readonly $make;
}

PHP throws the following error:

Fatal error: Readonly property Car::$make must have type

Difference from constants

Both readonly properties and constants in PHP share the feature of immutability, meaning that their value cannot be changed once it's set. However, they are used in different contexts and have different scopes and lifecycles. Here are some of the key differences:

Constants

  • Constants are defined using the define() function or the const keyword. They are not defined in the context of a class but rather in the global scope of a PHP script.
  • Once a constant is defined, it cannot be undefined or have its value changed.
  • Constants can be accessed anywhere in your script without an instance of a class.
  • Constants are often used for values that are known before execution begins and remain the same throughout the script, like database connection details, API keys, mathematical constants, etc.

Readonly properties

  • Readonly properties are a feature of objects (instances of classes) in PHP. They must be defined within a class.
  • They can be set a value only once during the object's instantiation (creation).
  • The value of a readonly property can be different for different instances of the same class. This is a significant difference from constants, which have the same value throughout the script.
  • Readonly properties are often used for values that are specific to a particular instance of a class and which should not change after the object's creation, like a database record's ID.

Here's an example for clarification:

class MyClass {
  public const CONSTANT_VALUE = "Hello, world! I'm a constant";
  public readonly string $readonlyProperty;
 
  public function __construct(string $value) {
      $this->readonlyProperty = $value;
  }
}
 
$instance1 = new MyClass("Hello");
$instance2 = new MyClass("World");
 
echo MyClass::CONSTANT_VALUE;  // Outputs: Hello, world! I'm a constant
echo $instance1->readonlyProperty;  // Outputs: Hello
echo $instance2->readonlyProperty;  // Outputs: World

In this example, MyClass::CONSTANT_VALUE has the same value everywhere in the script, but $readonlyProperty can have a different value for each instance of MyClass.

Key Takeaways

  • Readonly properties in PHP can be set only once during the object's instantiation (creation). After they're set, their value cannot be changed.
  • The value of a readonly property can be different for each instance of a class. This differentiates them from constants, which have the same value throughout the script.
  • Readonly properties are defined within a class. They are a feature of objects (instances of classes), unlike constants which are defined in the global scope of a script.
  • By declaring a property as readonly, you prevent accidental modifications to that property after the object's creation. If you try to modify a readonly property, PHP will give an error.
  • Readonly properties are ideal for values that should not change after an object's creation. Examples could be an ID value assigned to a database record, a birth date for a person object, or a creation timestamp for an event object.
  • The readonly properties feature was introduced in PHP version 8.1. If you're using an older version, you won't have access to this feature.

Comments

Please read this before commenting