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.*