Новые возможности

Ядро PHP

Типизированные свойства

Свойства класса теперь поддерживают объявления типов.

<?php

class User
{
public
int $id;
public
string $name;
}

?>
Приведённый пример показывает, что свойству $user->id получится присвоить только значения с типом int, тогда как свойству $user->name — только значения с типом string.

Стрелочные функции

Стрелочные функции — сокращённая запись для определения функций с неявной привязкой родительской области видимости по значению.

<?php

$factor
= 10;
$nums = array_map(fn ($n) => $n * $factor, [1, 2, 3, 4]);
// $nums = array(10, 20, 30, 40);

?>

Ограниченная ковариация возвращаемого типа и контравариантность типа аргумента

Следующий код теперь будет работать:

<?php

class A {}
class
B extends A {}

class
Producer
{
public function
method(): A {}
}

class
ChildProducer extends Producer
{
public function
method(): B {}
}

?>
Полная поддержка вариантности доступна только при автозагрузке классов. Нельзя ссылаться на типы циклически внутри одного файла, поскольку при ссылке на класс, который пока недоступен, возникает фатальная ошибка.
<?php

/**
* Класс удовлетворяет принципу подстановки Б. Ли́сков (англ. Liskov Substitution Principle, LSP),
* поскольку класс C принадлежит подтипу A,
* но при объявлении класса B класс C ещё недоступен
*/
class A
{
public function
method(): A {}
}

class
B extends A
{
// Fatal error: Could not check compatibility between B::method():C and
// A::method(): A, because class С is not available
public function method(): С {}
}

class
C extends B {}

?>

Присваивающий оператор объединения с null

<?php

$array
['key'] ??= computeDefault();

// Предыдущая проверка на null с присваиванием — примерно то же, что:
if (!isset($array['key'])) {
$array['key'] = computeDefault();
}

?>

Распаковка внутри массивов

<?php

$parts
= ['apple', 'pear'];

$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];

?>

Разделитель в числовых литералах

Между знаками числовых литералов теперь допускаются символы подчёркивания.

<?php

6.674_083e-11
; // число с плавающей точкой
299_792_458; // десятичное число
0xCAFE_F00D; // шестнадцатеричное число
0b0101_1111; // двоичное число

?>

Слабые ссылки

Слабые ссылки разрешают программисту хранить ссылку на объект, которая не препятствует уничтожению объекта сборщиком мусора, когда ссылок на объект не осталось.

Исключения в магическом методе __toString()

В магическом методе __toString() разрешили выбрасывать исключения. Раньше это вызывало фатальную ошибку. Существующие отлавливаемые фатальные ошибки при преобразовании объекта в строку преобразовали в исключения класса Error.

Модуль cURL

В дополнение к станадртным названиям файлов класс CURLFile теперь поддерживает потоковые обёртки, если модуль собрали с библиотекой libcurl >= 7.56.0.

Модуль Filter

Фильтр FILTER_VALIDATE_FLOAT теперь поддерживает параметры min_range и max_range, с тем же смыслом, что и фильтр FILTER_VALIDATE_INT.

Модуль FFI

FFI — новый модуль, который предлагает простой способ вызова библиотечных функций, доступа к встроенным переменным и способ создавать или обращаться к структурам данных, которые определили в библиотеках на языке Си.

Модуль GD

Добавили константу IMG_FILTER_SCATTER для применения рассеивающегося фильтра к изображениям.

Модуль Hash

Добавили поддержку алгоритма crc32c, который вычисляет «хеш» на основе полинома Кастаноли. С этой реализацией алгоритма CRC32 работают системы хранения наподобие iSCSI, SCTP, Btrfs и ext4.

Многобайтовые строки

Добавили функцию mb_str_split(), которая выполняет то же, что и функция str_split(), но работает с кодовыми точками, а не с байтами.

Модуль OPcache

Добавили поддержку предварительной загрузки кода.

Регулярные выражения, совместимые с синтаксисом языка Perl

Функции preg_replace_callback() и preg_replace_callback_array() теперь принимают дополнительный аргумент flags с поддержкой флагов PREG_OFFSET_CAPTURE и PREG_UNMATCHED_AS_NULL. Он повлияет на формат массива совпавших значений, передаваемого в callback-функцию.

Модуль PDO

Имя пользователя и пароль как часть DSN-строки разрешили указывать для драйверов mysql, mssql, sybase, dblib, firebird и oci. Раньше это поддерживалось только для драйвера pgsql. Конструктор будет приоритетнее, если имя пользователя с паролем указали и в конструкторе, и в DSN-строке.

В SQL-запросах разрешили экранировать вопросительные знаки, чтобы они не воспринимались как заполнители параметров. Запись ?? отправит один знак вопроса в базу данных, и разрешит, например при работе с СУБД PostgreSQL, указывать оператор ?, чтобы проверить, содержит ли столбец JSON конкретный ключ.

Драйвер PDO_OCI

Для драйвера теперь доступен метод PDOStatement::getColumnMeta().

Драйвер PDO_SQLite

Вызов PDOStatement::getAttribute(PDO::SQLITE_ATTR_READONLY_STATEMENT) проверит, доступен ли подготовленный запрос только для чтения, т. е. не изменяет ли запрос базу данных.

При установке PDO::setAttribute(PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES, true) методы PDO::errorInfo() и PDOStatement::errorInfo() возвращают расширенные коды ошибок СУБД SQLite3.

SQLite3

Добавили метод SQLite3::lastExtendedErrorCode(), который получает последний расширенный код ошибки.

Добавили метод SQLite3::enableExtendedResultCodes($enable = true), который заставит метод SQLite3::lastErrorCode() возвращать расширенные коды ошибок.

Стандартные функции языка

Функция strip_tags() с массивом имён тегов

Функция strip_tags() теперь также принимает массив разрешённых тегов: вместо strip_tags($str, '<a><p>') теперь можно написать strip_tags($str, ['a', 'p']).

Пользовательская сериализация объектов

Добавили новый механизм сериализации пользовательских объектов через два новых магических метода: __serialize и __unserialize.

<?php

// Метод возвращает массив с данными для сохранения целостного состояния объекта
public function __serialize(): array {}

// Восстанавливает состояние объекта из массива данных
public function __unserialize(array $data): void {}

?>
Новый механизм сериализации заменяет интерфейс Serializable, который в будущем объявят устаревшим.

Функции слияния массивов без аргументов

Функции array_merge() и array_merge_recursive() стали поддерживать вызов без аргументов. При вызове без аргументов функции возвращают пустой массив. Функции также полезно вызывать с распаковкой аргумента spread-оператором: array_merge(...$arrays).

Функция proc_open()

Функция proc_open() теперь принимает массив вместо строки для выполнения команды. При таком вызове процесс открывается напрямую, без командной оболочки, а PHP экранирует аргументы, если потребуется.

<?php

proc_open
(['php', '-r', 'echo "Привет, мир\n";'], $descriptors, $pipes);

?>

Функция proc_open() теперь поддерживает дескрипторы redirect и null.

<?php

// То же самое, что и 2>&1 в командной оболочке
proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['redirect', 1]], $pipes);

// То же самое, что и 2>/dev/null или 2>nul в командной оболочке
proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['null']], $pipes);

?>

Алгоритмы Argon2i и argon2id без библиотеки libargon

Функция password_hash() теперь поддерживает варианты хеширования argon2i и argon2id из модуля Sodium, если PHP собрали без библиотеки libargon.