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, perf)
Типизированные свойства
У свойств класса можно объявлять типы. Неинициализированное 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
Arrow functions (fn) захватывают переменные из окружения по значению и возвращают одно выражение — удобно для коротких колбэков.
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3]);
fn — зарезервированное слово: нельзя назвать функцию или класс fn (имена методов/констант допускаются).
Ковариантность и контравариантность
Типы возвращаемых значений могут сужаться (ковариантность), типы параметров — расширяться (контравариантность) при наследовании, с ограничениями. Полная вариантность лучше работает при autoload; в одном файле допустимы только нециклические ссылки на классы.
Оператор присваивания с null coalescing (??=)
Присваивание выполняется, если слева не задано или 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: вызов нативных библиотек из PHP (мощно; нужны модель угроз и ограничения).
- 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*появился аргументflags(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,bool,int,float,resourceвида$x['k']— notice. get_declared_classes(): не возвращает анонимные классы, пока они не инстанциированы.fn: зарезервировано для имён функций/классов.<?phpв конце файла без перевода строки: теперь это открывающий тег (раньше поведение зависело отshort_open_tag).- Stream wrappers: при
include/requireпо stream может вызываться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: дамп
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. - Cookies (с 7.4.11): имена cookie не URL-декодируются.
Deprecated (исправить заранее)
Главное:
- Вложенные тернарные операторы без явных скобок (кроме однозначной формы с вложением в средний операнд).
- Фигурные скобки для смещения
$str{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()и строковое приведение reflection-объектов.allow_url_include,FILTER_SANITIZE_MAGIC_QUOTES, устаревшие LDAP paged helper’ы, ряд функций (money_format(),hebrevc(), …) — полный список: migration74 deprecated.
Прочие изменения и эксплуатация (сборка, INI, perf)
zend.exception_ignore_args: новый INI (по умолчанию может скрывать аргументы в stack trace — проверьте логирование ошибок).opcache.preload_user: пользователь для preload не из-под root.- Миграция на pkg-config: многие
./configureбольше не принимают=DIR; используйтеPKG_CONFIG_PATHилиFOO_CFLAGS/FOO_LIBS. - Убраны бандлы: SQLite3, Zip, onig (mbregex) — нужны системные библиотеки; hash всегда включён.
- CSV: пустая строка
$escapeотключает escape-механизм PHP; поведениеstr_getcsv()согласовано. - GD: поведение
imagecropauto()приведено к system libgd; изменён дефолтный режим; дляimagescale()-1по ширине/высоте сохраняет пропорции. - PEAR: по умолчанию не ставится (
--with-pearопционально и deprecated). - Производительность: opcode для
array_key_exists()при статическом разрешении; UTF-8preg_matchвалидирует строку один раз при повторных вызовах.
Итог
Считайте PHP 7.4 мостом к 8.x: внедряйте typed properties и современную сериализацию до жёстких ошибок восьмёрки. Параллельно прогоните поиск по целочисленным PASSWORD_*, именам fn, синтаксису $var{idx} и шаблонам с ArrayObject — и прогоните интеграционные тесты для streams, OpenSSL random и сериализации PDO/Reflection.