readonly + accessors

readonly + accessors

Стабільні DTO і Value Object без бойлерплейту

  • Додано у версіях: readonly — PHP 8.1, accessors — PHP 8.4
  • Що це дає: можливість створювати об’єкти, дані в яких неможливо змінити випадково, та новий синтаксис контролю доступу до властивостей через get / set без окремих методів.

В чому суть

readonly робить властивість незмінною після ініціалізації — значення можна встановити лише один раз (зазвичай у конструкторі).

accessors дозволяють додати контроль при читанні та записі властивостей без класичних геттерів і сеттерів — прямо в тілі класу.

Разом вони створюють ідеальну комбінацію для DTO, VO і конфігураційних класів: дані незмінні, а доступ контрольований.

Приклад класичного підходу

class Product {
    private string $name;
    private float $price;

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

    public function getPrice(): float {
        return $this->price;
    }

    public function setPrice(float $price): void {
        if ($price < 0) {
            throw new InvalidArgumentException('Price must be positive');
        }
        $this->price = $price;
    }
}

Працює, але більша частина коду тут тільки заради забезпечення базової інкапсуляції.

Тепер те саме — сучасно

class Product {
    public readonly string $name;
    private float $price {
        get => $this->price;
        set => $this->price = max(0, $value);
    }

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

readonly гарантує незмінність імені, accessors автоматично перевіряють ціну при записі.

Ще приклад — Value Object

class Coordinates {
    public readonly float $lat {
        get => round($this->lat, 6);
    }

    public readonly float $lng {
        get => round($this->lng, 6);
    }

    public function __construct(float $lat, float $lng)
    {
        $this->lat = $lat;
        $this->lng = $lng;
    }
}

Ніяких змін після створення, тільки контрольований доступ при читанні.

Де це реально корисно

  • DTO: запити й відповіді в API;
  • Value Object: Money, Price, GeoPoint, Range;
  • Immutable конфігурації: параметри сервісів, константні стани.

Висновок

readonly і accessors — це крок до справжніх record-класів у PHP. Вони дозволяють писати чисті, передбачувані структури без тонни бойлерплейту.

Сьогодні кожен мій DTO — readonly.

← Попередня: Enums · Уся серія · Наступна: Атрибути →


Вперше опубліковано в Telegram-каналі «Створений щоб помирати» 30.11.2025.