У листопаді минулого року вийшла PHP 8.3. Нова версія включає низку покращень — підвищено продуктивність, удосконалено сумісність типів, додано нові функції та виправлено виявлені помилки. Розглянемо найважливіші зміни, що підвищили якість релізу.
Система типів
Ця частина є найвразливішою у PHP, тому з кожним релізом розробники поступово вдосконалюють простір сумісності типів мови. У новій версії з’явилася можливість типізації констант класів, а також покращено механізм отримання констант класів і об’єктів перерахувань (Enum).
Типізація констант класів
У попередніх версіях мови тип і значення оголошеної всередині класу константи могли бути радикально змінені в дочірніх класах чи інтерфейсах, що вносило плутанину в код і могло стати причиною серйозних помилок.
Наприклад, у старих версіях PHP:
class Testing_oldversion {
const string NEW_CONSTANT = 'oldversion';
}
class Testing_oldversion {
const string NEW_CONSTANT = [];
}Тут константа NEW_CONSTANT не лише «втратила» своє початкове значення, а й була змінена зі строкового типу на масив — і при цьому інтерпретатор продовжував виконання коду без помилки.
Починаючи з PHP 8.3, такі перевизначення більше неможливі, оскільки константи класів стали типізованими. Якщо у дочірньому класі чи інтерфейсі змінити тип константи, інтерпретатор виведе Fatal error і припинить виконання програми. Це додає коду передбачуваності та впорядкованості — ще один крок до покращення системи типів у PHP.
Оголосити тип константи тепер можна безпосередньо після ключового слова const, наприклад:
class Testing_newversion {
const string NEW_CONSTANT = 'newversion';
}
class Testing_newversion {
const string NEW_CONSTANT = [];
}
// Fatal error: Cannot use array as value for class constant Testing_newversion::NEW_CONSTANT of type stringЯк бачимо, інтерпретатор виводить повідомлення про фатальну помилку та зупиняє виконання коду.
Динамічне отримання констант класів і об’єктів Enum
У попередніх версіях PHP не можна було динамічно отримати константи класів або об’єкти Enum через змінну — конструкція ClassName::{$varName} не підтримувалася, і спроба її використати призводила до синтаксичної помилки.
Старий приклад:
enum OldEnum: int {
case OldMember = 30;
}
$enumName1 = 'OldMember';
echo OldEnum::{$enumName1}->value;Результат:
Parse error: syntax error, unexpected token "->", expecting "("Новий приклад у PHP 8.3:
class NewClass {
public const NEW_CONST = 35;
}
$constName1 = 'NEW_CONST';
echo NewClass::{$constName1};Тепер конструкція ClassName::{$varName} є допустимою, і код виконується без помилок.
Коректне перевизначення методів класу або інтерфейсу
До PHP 8.3 могла виникнути ситуація, коли розробник випадково використовував ім’я методу, вже оголошеного в батьківському класі чи інтерфейсі, що призводило до неочікуваного перевизначення.
Щоб уникнути цього, у новій версії додано атрибут #[\Override], який запобігає випадковим перевизначенням.
Тепер перевизначення можливе лише тоді, якщо перед методом явно вказано цей атрибут. Якщо ж атрибут є, а батьківський метод відсутній — інтерпретатор виведе Fatal error.
Некоректний приклад:
class OneTest {
#[\Override]
public function newMethod(): void {}
}Результат:
Fatal error: OneTest::newMethod() has #[\Override] attribute, but no matching parent method exists
Правильний приклад:
class MainClass {
public function newMethod() {}
}
class ChildrenClass extends MainClass {
#[\Override]
public function newMethod() {}
}Атрибут також можна використовувати для методів Enum і Trait:
interface MainInterface {
public function oneMethod(): void;
}
enum ChildrenEnum implements MainInterface {
#[\Override]
public function oneMethod(): void {}
}
trait MainTrait {
#[\Override]
public function testMethod() {}
}
class NewClass {
use MainTrait;
public function testMethod(): void {}
}В обох випадках використання атрибута є коректним і допомагає уникнути типових помилок попередніх версій.
Перевірка на відповідність JSON-формату
У PHP 8.3 з’явилася нова функція json_validate(), яка перевіряє, чи відповідає рядок синтаксису JSON.
На відміну від json_decode(), нова функція не виконує розбір рядка, тому споживає значно менше ресурсів процесора та пам’яті.
Приклади:
var_dump(json_validate('{ "onetesting": { "less": "moo" } }')); // true
json_validate(""); // false
json_validate("null"); // trueФункція не повертає код помилки, тому для цього, як і раніше, можна використовувати json_last_error() та json_last_error_msg().
Нові методи класу Randomizer
Клас Randomizer, доданий у попередній версії PHP, отримав нові методи для різних форматів генерації випадкових чисел.
Генерація чисел з плаваючою комою
Методи getFloat() і nextFloat() дозволяють генерувати випадкові дійсні числа в заданому інтервалі без зміщення та проблем з округленням.
$rdm = new \Random\Randomizer();
$allvalue = $rdm->getFloat(
-5.2,
30.7,
\Random\IntervalBoundary::ClosedClosed,
);
$valueTrue = 0.1;
$mainBool = $rdm->nextFloat() < $valueTrue;
Генерація випадкових байтів
Метод getBytesFromString() дозволяє створювати рядки з певної кількості байтів — наприклад, для генерації ідентифікаторів або випадкових піддоменів.
$rdm = new \Random\Randomizer();
$randomMyDomain = sprintf(
"%s.site.ua",
$rdm->getBytesFromString(
'abcdefghijk01234567',
7,
),
);
echo $randomMyDomain;
У цьому прикладі створюються випадкові імена піддоменів для сайту site.ua, що складаються з семи випадкових символів із заданого набору.
