PHP 7.4: Головні нововведення
PHP 7.4 — останній мінор 7.x перед гілкою 8.0: у мові з’являються типізовані властивості, arrow functions, обмежена коваріантність/контраваріантність і зручний синтаксис (??=, spread у масивах, роздільники в числах). Паралельно додаються FFI, OPcache preloading і сучасна пара __serialize / __unserialize. Під час міграції тримайте в полі зору: ініціалізацію typed properties, рядкові константи алгоритмів паролів, збірку та розширення (SQLite/Zip більше не в бандлі, перехід на pkg-config).
Зміст
- Типізовані властивості
- Arrow functions
- Коваріантність і контраваріантність
- Присвоєння з null coalescing (
??=) - Оператор spread у масивах
- Роздільник у числових літералах
- Слабкі посилання (WeakReference)
- Винятки з
__toString() - Серіалізація:
__serialize/__unserialize - Розширення і стандартна бібліотека
- Практичні рецепти
- Зворотно несумісні зміни (міграційні нотатки)
- Deprecated (виправити завчасно)
- Інші зміни та експлуатація (збірка, INI, продуктивність)
Типізовані властивості
У властивостей класу можна оголошувати типи. Неініціалізовану typed property не можна читати до присвоєння — буде Typed property ... must not be accessed before initialization.
final class User
{
public int $id;
public string $name;
public ?string $nickname = null;
}
З практики:
- Якщо «немає значення» допустимо —
?Typeабо значення за замовчуванням. - Тип
callableдля властивостей не підтримується. - Об’єктні typed properties мають обмеження на оголошенні — див. мануал.
Arrow functions
fn захоплює змінні з оточення за значенням і повертає один вираз — зручно для коротких колбеків.
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3]);
fn — зарезервоване слово: не можна назвати функцію чи клас fn (методи/константи — дозволено).
Коваріантність і контраваріантність
Типи повернення можна звужувати, типи параметрів — розширювати при успадкуванні, з обмеженнями. Повна варіантність краще працює з autoload; в одному файлі дозволені лише нециклічні посилання на класи.
Присвоєння з null coalescing (??=)
Присвоєння виконується, якщо зліва unset або null:
$config['debug'] ??= false;
Оператор spread у масивах
Розпакування ітерованих значень у літералі масиву:
$base = [1, 2];
$all = [0, ...$base, 3]; // [0, 1, 2, 3]
Добре поєднується з array_merge(...$arrays); array_merge() без аргументів повертає [].
Роздільник у числових літералах
Підкреслення покращують читання і не змінюють значення:
$million = 1_000_000;
$hex = 0xFF_FF_FF;
Слабкі посилання (WeakReference)
WeakReference тримає посилання, яке не заважає збирати об’єкт сміттєзбирачем — корисно для кешів.
Винятки з __toString()
Кидати винятки з __toString() дозволено (раніше — fatal). Частина старих recoverable fatals стала Error — перевірте приведення до рядка.
Серіалізація: __serialize / __unserialize
Новий механізм, що поступово витісняє Serializable:
final class Point
{
public function __serialize(): array
{
return ['x' => $this->x, 'y' => $this->y];
}
public function __unserialize(array $data): void
{
$this->x = $data['x'];
$this->y = $data['y'];
}
}
Типи SPL на кшталт ArrayObject можуть записувати нові серіалізовані представлення, читані на 7.4+, але не на старіших PHP.
Розширення і стандартна бібліотека
- FFI: виклик нативних бібліотек (потрібна модель загроз).
- OPcache preloading:
opcache.preload, частоopcache.preload_user. mb_str_split(): якstr_split(), але по кодпойнтах.proc_open(): команда масивом (без shell), дескрипториredirect/null.strip_tags(): дозволені теги масивом імен.- PDO: логін/пароль у DSN для більшої кількості драйверів;
??у SQL екранує літеральний?(наприклад для JSON-операторів у PostgreSQL). - PCRE:
preg_replace_callback*приймає прапорці —PREG_OFFSET_CAPTURE,PREG_UNMATCHED_AS_NULLтощо. - Password: Argon2 через sodium без libargon.
Практичні рецепти
Безпечні значення за замовчуванням з ??=
$options['timeout'] ??= 30;
Arrow function у сортуванні
usort($rows, fn($a, $b) => $a['score'] <=> $b['score']);
Spread-merge динамічних списків
$merged = array_merge(...$chunks);
Зворотно несумісні зміни (міграційні нотатки)
Ядро
- Доступ як до масиву до не-масивів:
$null["key"]та подібне дляnull,bool,int,float,resource— notice. get_declared_classes(): більше не повертає анонімні класи, доки їх не інстанційовано.fn: зарезервоване ключове слово для імен функцій/класів.<?phpв кінці файлу без нового рядка: тепер трактується як відкриваючий PHP-тег (раніше залежало відshort_open_tag).- Stream wrappers: під час
include/requireпо stream може викликатисяstreamWrapper::stream_set_option(STREAM_OPTION_READ_BUFFER)— реалізуйте метод або повертайтеfalse, щоб не було warning. - Серіалізація: формат
oприбрано (актуально лише для вручну складених рядків). - Константи алгоритмів паролів:
PASSWORD_*— це рядки ('2y','argon2id', …), не цілі — код з порівнянням з1/2/3ламається. htmlentities(): notice, коли кодування зводиться до поведінки як уhtmlspecialchars.fread/fwrite: при невдачі повертаютьfalse(не''/0); можливий notice.- BCMath: попередження для некоректних числових рядків (раніше часто трактувалися як нуль).
- CURL: серіалізація
CURLFileкидає раніше; нестандартний аргументcurl_version()— попередження/ігнорування. - Date:
var_dumpдляDateInterval/DateTime*без «зайвих» властивостей; порівнянняDateIntervalпопереджає і завжди даєfalse. - Intl: за замовчуванням
idn_to_ascii/idn_to_utf8використовуютьINTL_IDNA_VARIANT_UTS46. - MySQLi: прибрано embedded server; прибрано недокументоване
$mysqli->stat— користуйтесяmysqli::stat(). - OpenSSL:
openssl_random_pseudo_bytesкидає якrandom_bytesпри помилці;$crypto_strong—true, якщо винятку немає. - PCRE: з
PREG_UNMATCHED_AS_NULLхвостові неспівпадіння груп —null(стабільний розмір$matches). - PDO: серіалізація
PDO/PDOStatementкидаєException(неPDOException). - Reflection: серіалізація reflection-об’єктів кидає; змінено числові значення деяких констант модифікаторів.
- SPL /
ArrayObject: змінена поведінкаget_object_varsбезSTD_PROP_LIST;SplPriorityQueue::setExtractFlags(0)кидає одразу. - Tokenizer: несподівані байти стають
T_BAD_CHARACTERзамість «пробілів» у потоці. - Cookie (з 7.4.11): імена вхідних cookie не URL-декодуються.
Deprecated (виправити завчасно)
Акценти:
- Вкладені тернарні оператори без явних дужок (окрім однозначної форми з вкладенням у середній операнд).
- Фігурні дужки для offset
$str{0}/$arr{0}→ використовуйте[]. (real)іis_real()→(float)/is_float().array_key_exists()для об’єктів →isset()/property_exists().implode($parts, $glue)— зворотний порядок →implode($glue, $parts).ReflectionType::__toString()іReflection*::export()→ API на кшталтReflectionNamedType::getName()і string cast reflection-об’єктів.allow_url_include,FILTER_SANITIZE_MAGIC_QUOTES, застарілі LDAP paged-функції,money_format(),hebrevc()тощо — повний список: migration74 deprecated.
Інші зміни та експлуатація
zend.exception_ignore_args: новий INI (за замовчуванням може приховувати аргументи у stack traces — перевірте error reporting).opcache.preload_user: користувач для preload, коли не root.- Міграція на pkg-config: багато
./configure-прапорів більше не приймають=DIR; використовуйтеPKG_CONFIG_PATHабоFOO_CFLAGS/FOO_LIBS. - Прибрані бандли: SQLite3, Zip, onig (mbregex) — потрібні системні бібліотеки; hash завжди вбудований.
- CSV: порожній рядок для
$escapeвимикає PHP escape-механізм;str_getcsv()узгоджено. - GD:
imagecropauto()узгоджено з системною libgd; змінено режим за замовчуванням;imagescale()з-1зберігає пропорції. - PEAR: не встановлюється за замовчуванням (
--with-pearопційно і deprecated). - Продуктивність: opcode для
array_key_exists()при статичному розв’язанні; UTF-8preg_matchвалідує рядок один раз при повторних викликах.
Підсумок
PHP 7.4 — міст до 8.x: впровадьте typed properties і __serialize/__unserialize заздалегідь; шукайте цілі PASSWORD_*, ім’я fn, синтаксис $var{idx} і крихкий код з ArrayObject; тестуйте streams, OpenSSL random і серіалізацію PDO/Reflection.