2.8Kпросмотров
31 августа 2025 г.
statsScore: 3.0K
PHP 8.5: Clone with - майже те, що треба Готувався до подкасту, де будемо розглядати нові можливості PHP 8.5 і неочікувано натрапив те, що цю фічу вже імплементували. Я був шокований, адже я чекав цього ще з моменту, як ввели readonly property (php8.1), навіть був RFC, котрий заглох, а тут бах, і вже змержили. Що правда не все супер райдужно, адже фактично створили новий RFC і імплементацію розділили на кілька етапів. То давайте розбиратись ❓ Чим круті readonly properties та іммутабельні обʼєкти ► Не треба гратись з інкапсуляцією, створювати додаткові getters/setters
► Ніхто випадково не поміняє дані десь в глибині коду
► Можна безпечно передавати об'єкт кудись - він точно повернеться таким самим
► Легше дебажити - об'єкт не може магічно змінитись між рядками коду
► Thread safety з коробки (якщо раптом дійде до async в PHP 9) Але все це круто до моменту поки ми не захочемо щось з цим обʼєктом таки зробити [pic | code] І через це пилили костилі, приходилось або писати купу окремих with методів [pic | code] (просто копіпасту), або гратись з рефлексією, що також є ресурсозатратно і не зовсім надійно [pic | code] І тепер в PHP 8.5 ми зможемо досягти результату дуже просто $mariaViolin = clone($maria, ['instrument' => 'скрипка']); Ну майже просто 😅 🗿 Які є підводні камені? Справа в тому, що ми не можемо просто взяти і зробити це без додаткових дій, адже коли в PHP 8.4 формалізували asymmetric visibility (можна окремо задавати видимість для читання і запису), стало зрозуміло, що всі public readonly властивості по дефолту були public(get) protected(set). Чому protected(set) а не public(set) за замовчуванням, бо readonly властивості з самого початку (PHP 8.1) були задумані як "встановлюються тільки в конструкторі". Ну і не private(set), щоб можна було цим керувати в дочірніх класах 👉 Саме тому, при спробі викликати клонування в 8.5 поза обʼєктом призведе до відповідної помилки [pic | code], тому треба про це памʼятати і якщо необхідно - явно вказувати public(set) для властивостей вашого обʼєкту [pic | code] 💡 Або, робити відповідні зміни прямо всередині вашого обʼєкта, додаючи відповідні методи [pic | code], що мені подобається більше, але підійде не для всіх випадків. 🤔 Чи по тій самій схемі, замінити страшний приклад з рефлексією на реалізацію простого with [pic | code] Ще один важливий момент Поточна реалізація ніяк не впливає на використання магічного метода clone, тобто параметри в нього досі передавати не можна, а при його імплементації ми отримаємо копію обʼєкту БЕЗ урахування того, що ми передали в якості аргументу [pic | code]. Це було свідоме рішення під час розбиття rfc на різні етапи, бо ця фіча ломає BC і сильно ускладнює імплементацію 💪 І тим не менш, я думаю, що Clone with - це крок в правильному напрямку Поки памʼятаємо про protected(set) для readonly, скоріш за все це зміниться, та clone() без параметрів, котрі обіцяють додати в майбутньому. Але навіть з усіма нюансами - це краще ніж те, чим ми користувались. А ви що думаєте? Будете використовувати clone with? #php85 #readonly #clonewith #middle #source