readonly + accessors

← readonly + accessors

Ashterix

docs: English JsonRpcBundle docs, REST and MCP Bundle sections, package cards

uk/articles/from-tg/series/php-can-do/readonly.md новий файл +103 −0

1 + # readonly + accessors
2 +
3 + *Стабільні DTO і Value Object без бойлерплейту*
4 +
5 + - **Додано у версіях:** readonly — PHP 8.1, accessors — PHP 8.4
6 + - **Що це дає:** можливість створювати об’єкти, дані в яких неможливо змінити випадково, та новий синтаксис контролю доступу до властивостей через get / set без окремих методів.
7 +
8 + ## В чому суть
9 +
10 + `readonly` робить властивість незмінною після ініціалізації — значення можна встановити лише один раз (зазвичай у конструкторі).
11 +
12 + `accessors` дозволяють додати контроль при читанні та записі властивостей без класичних геттерів і сеттерів — прямо в тілі класу.
13 +
14 + Разом вони створюють ідеальну комбінацію для DTO, VO і конфігураційних класів: дані незмінні, а доступ контрольований.
15 +
16 + ## Приклад класичного підходу
17 +
18 + ```php
19 + class Product {
20 + private string $name;
21 + private float $price;
22 +
23 + public function __construct(string $name, float $price)
24 + {
25 + $this->name = $name;
26 + $this->price = $price;
27 + }
28 +
29 + public function getPrice(): float {
30 + return $this->price;
31 + }
32 +
33 + public function setPrice(float $price): void {
34 + if ($price < 0) {
35 + throw new InvalidArgumentException('Price must be positive');
36 + }
37 + $this->price = $price;
38 + }
39 + }
40 + ```
41 +
42 + Працює, але більша частина коду тут тільки заради забезпечення базової інкапсуляції.
43 +
44 + ## Тепер те саме — сучасно
45 +
46 + ```php
47 + class Product {
48 + public readonly string $name;
49 + private float $price {
50 + get => $this->price;
51 + set => $this->price = max(0, $value);
52 + }
53 +
54 + public function __construct(string $name, float $price)
55 + {
56 + $this->name = $name;
57 + $this->price = $price;
58 + }
59 + }
60 + ```
61 +
62 + `readonly` гарантує незмінність імені, `accessors` автоматично перевіряють ціну при записі.
63 +
64 + ## Ще приклад — Value Object
65 +
66 + ```php
67 + class Coordinates {
68 + public readonly float $lat {
69 + get => round($this->lat, 6);
70 + }
71 +
72 + public readonly float $lng {
73 + get => round($this->lng, 6);
74 + }
75 +
76 + public function __construct(float $lat, float $lng)
77 + {
78 + $this->lat = $lat;
79 + $this->lng = $lng;
80 + }
81 + }
82 + ```
83 +
84 + Ніяких змін після створення, тільки контрольований доступ при читанні.
85 +
86 + ## Де це реально корисно
87 +
88 + - `DTO`: запити й відповіді в API;
89 + - `Value Object`: Money, Price, GeoPoint, Range;
90 + - `Immutable конфігурації`: параметри сервісів, константні стани.
91 +
92 + ## Висновок
93 +
94 + > readonly і accessors — це крок до справжніх record-класів у PHP.
95 + > Вони дозволяють писати чисті, передбачувані структури без тонни бойлерплейту.
96 +
97 + Сьогодні кожен мій DTO — readonly.
98 +
99 + ← [Попередня: Enums](/articles/from-tg/series/php-can-do/enums) · [Уся серія](/articles/from-tg/series/php-can-do) · [Наступна: Атрибути →](/articles/from-tg/series/php-can-do/attributes)
100 +
101 + ---
102 +
103 + *Вперше опубліковано в Telegram-каналі [«Створений щоб помирати»](https://t.me/php_while_true/95) 30.11.2025.*