PHP 8 news: Readonly properties
Tags: php
Published: 2024-03-24 00:40:13

In `PHP 8.1`, `readonly` properties were introduced, which allow you to declare class properties that can only be set once during object initialization and cannot be modified thereafter. This feature brings more immutability to PHP classes, enhancing code reliability and readability. Here's an explanation along with examples:

**Syntax:**

```php
class MyClass {

    public readonly string $name;
    public readonly int $age;

    public function __construct(string $name, int $age) {
        $this->name = $name;
        $this->age = $age;
    }
}
```

- The **`readonly`** keyword is used to declare properties that are immutable after initialization.
- These properties must be initialized either at the point of declaration or within the constructor.
- Once initialized, their values cannot be modified throughout the object's lifetime.

**Example:**

```php
class Person {

    public readonly string $name;
    public readonly int $age;

    public function __construct(string $name, int $age) {
        $this->name = $name;
        $this->age = $age;
    }
}

$person = new Person("Zero", 24);
echo "Name: " . $person->name . ", Age: " . $person->age . "\n";

// Trying to modify readonly properties will result in a fatal error
// $person->name = "Jane";
// $person->age = 25;
```
In this example, the `Person` class has `readonly` properties `$name` and `$age`. They are initialized within the constructor. Once initialized, their values cannot be changed.

If you uncomment the lines trying to modify the `readonly` properties, PHP will throw a fatal error indicating that the properties are read-only and cannot be modified.

**Benefits:**

1. **Immutability:** Readonly properties ensure that once set, their values remain constant throughout the object's lifetime, enhancing predictability and reducing unexpected side effects.
2. **Code Safety:** It prevents accidental modification of properties, reducing the chances of bugs and making code more robust.
3. **Readability:** By indicating that certain properties are readonly, it clarifies the intent of the class and its usage to other developers.

Overall, readonly properties in `PHP 8.1` offer a convenient way to create more immutable and reliable classes.

### More examples:

**Example 1: Immutable Point Class**

```php
class Point {

    public readonly float $x;
    public readonly float $y;

    public function __construct(float $x, float $y) {
        $this->x = $x;
        $this->y = $y;
    }

    public function __toString(): string {
        return "($this->x, $this->y)";
    }
}

$point = new Point(5.5, 3.2);
echo "Point coordinates: $point\n";
```
In this example, the `Point` class represents a point in a two-dimensional space. Both `$x` and `$y` properties are declared as `readonly`. Once initialized in the constructor, they cannot be modified. This ensures that the coordinates of a point remain immutable after creation.

**Example 2: Immutable Configuration Class**

```php
class Configuration {

    public readonly array $settings;

    public function __construct(array $settings) {
        $this->settings = $settings;
    }

    public function get(string $key) {
        return $this->settings[$key] ?? null;
    }
}

$config = new Configuration(['debug' => true, 'max_connections' => 10]);
echo "Debug mode: " . ($config->get('debug') ? 'On' : 'Off') . "\n";
```
Here, the `Configuration` class stores an array of settings. The `$settings` property is declared as `readonly` to ensure that once the configuration is initialized, it cannot be altered. This helps maintain the integrity of configuration data.

**Example 3: Readonly Properties in Inheritance**

```php
class ParentClass {

    public readonly string $parentProperty;

    public function __construct(string $parentProperty) {
        $this->parentProperty = $parentProperty;
    }
}

class ChildClass extends ParentClass {

    public readonly string $childProperty;

    public function __construct(string $parentProperty, string $childProperty) {
        parent::__construct($parentProperty);
        $this->childProperty = $childProperty;
    }
}

$child = new ChildClass('Parent', 'Child');
echo "Parent Property: {$child->parentProperty}, Child Property: {$child->childProperty}\n";
```
In this example, `ChildClass` extends `ParentClass`, and both classes have `readonly` properties. Even in inheritance, the `readonly` nature of properties is maintained, ensuring that once set, properties cannot be modified.

These examples showcase how `readonly` properties can be used to create immutable objects and maintain data integrity in various scenarios.