Версия PHP 8.1 находится в активной разработке и будет выпущена 25 ноября 2021 г. Следует иметь в виду, что эта дата может измениться, если основная команда разработчиков решит, например, добавить дополнительный бета-выпуск. Мы уже знаем о новых возможностях, повышении производительности, изменениях и упразднении сомнительной функциональности. Давайте рассмотрим эти новшества по порядку.
Новые возможности
Как и в каждом выпуске, в PHP 8.1 добавлено несколько новых полезных возможностей. Имейте в виду, что в течение года этот список будет пополняться.
Перечисления rfc
В PHP 8.1 будут добавлены перечисления (enum)! Если вы не уверены, зачем они нужны, можете прочитать о них здесь.
Добавление перечислений будет значительным улучшением PHP — я, например, с нетерпением жду их появления в PHP 8.1. Вот пример того, как они будут выглядеть:
enum Status { case Pending; case Active; case Archived; }
И вот как они будут использоваться:
Более подробно о том, как можно использовать перечисления, вы можете узнать из уже упомянутой статьи.
Файберы rfc
Файберы (fiber), или «зеленые потоки», представляют собой низкоуровневый механизм управления параллелизмом. Возможно, вам не придется использовать их в своих приложениях напрямую, но они будут широко применяться такими фреймворками, как Amphp и ReactPHP.
Вот простой пример использования файберов:
$fiber = new Fiber( function (): void { $valueAfterResuming = Fiber::suspend('после приостановки'); });$valueAfterSuspending = $fiber->start();
$fiber->resume('после возобновления');
Если вы хотите узнать больше о файберах и о том, что они могут и чего не могут делать, прочтите эту статью.
Повышение производительности pr
Дмитрий Стогов добавил в opcache ряд улучшений, назвав их кешем наследования (inheritance cache). Эта возможность позволяет кешировать связи между классами и очень похожа на предзагрузку связанных классов в PHP 7.4.
Дмитрий сообщает, что в результате производительность повышается на 5–8 %, — одна из приятных мелочей, ожидаемых от PHP 8.1.
Распаковка массивов со строковыми ключами rfc
Распаковка массивов была доступна еще в PHP 7.4, но работала только с числовыми ключами. Строковые ключи не поддерживались, так как не было единого мнения относительно объединения дубликатов в массивах. В данном RFC эта проблема четко решается путем следования семантике array_merge:
$array1 = ["a" => 1];Новый тип never rfc$array2 = ["b" => 2];
$array = ["a" => 0, ...$array1, ...$array2];
var_dump($array); #["a" => 1, "b" => 2]
Тип never можно использовать для указания того, что функция будет останавливать поток выполнения программы. Это можно сделать вызовом исключения или функции exit либо подобных ей.
function dd(mixed $input): never { dump($input);exit;
}
never отличается от void тем, что void позволяет программе продолжить выполнение. Этот тип может показаться необычным новшеством, но на деле он будет весьма полезен для статических анализаторов.
Новая функция array_is_list rfc
Возможно, вы имели дело с задачами, когда нужно было определить, представляют ли ключи массива числовую последовательность 0, 1, 2, 3..., подобно тому, как функция json_encode определяет, следует ли кодировать массив как массив или как объект.
В PHP 8.1 добавлена встроенная функция для определения того, является ли массив списком с такой семантикой или нет:
$list = ["a", "b", "c"];Начиная с PHP 8.1 такие константы можно помечать словом final, чтобы исключить эту возможность:array_is_list($list); # true
$notAList = [1 => "a", 2 => "b", 3 => "c"];
array_is_list($notAList); # false
$alsoNotAList = ["a" => "a", "b" => "b", "c" => "c"];
array_is_list($alsoNotAList); # false
Финальные константы классов rfc
Константы классов в PHP могут быть переопределены при наследовании:
class Foo
{
public const X = "foo";
}class Bar extends Foo
{
public const X = "bar";
}
class Foo { final public const X = "foo"; }class Bar extends Foo
{
public const X = "bar";
Fatal error: Bar::X cannot override final constant Foo::X
}
Новая функция fsync rfc
В PHP 8.1 добавлены функции fsync и fdatasync, выполняющие перед возвратом принудительную синхронизацию изменений файла с диском и обеспечивающие очистку буферов записи операционной системы.
$file = fopen("sample.txt", "w");fwrite($file, "Какое-то содержимое");
if (fsync($file)) {
echo "Файл успешно сохранен на диск.";
}fclose($file);
Поскольку синхронизация c диском — это операция файловой системы, функция fsync будет работать только с обычными файловыми потоками. При попытке синхронизации нефайловых потоков будет выдаваться предупреждение.
Явная нотация восьмеричных целочисленных литералов rfc
Теперь для обозначения восьмеричных чисел можно использовать префиксы 0o и 0O. Ранее принятая нотация, согласно которой к числу следовало добавлять префикс 0, также по-прежнему будет работать.
016 === 0o16; # trueИзменения, которые могут затронуть существующий код016 === 0O16; # true
Хотя PHP 8.1 является младшей версией, она упраздняет некоторую сомнительную функциональность, а также вносит изменения, которые технически могут испортить уже существующий код. Давайте поговорим об этих нововведениях.
Ограничение использования $GLOBALS rfc
Небольшое изменение условий работы с массивом $GLOBALS существенно повлияет на производительность всех операций с массивами. Никита Попов отлично объяснил проблему и ее решение в соответствующем RFC. Суть изменения в том, что с массивом $GLOBALS теперь нельзя будет выполнять некоторые редко используемые операции. «Перезапись $GLOBALS как единого целого отныне не поддерживается. Все приведенные ниже инструкции вызовут ошибку во время компиляции»:
$GLOBALS = [];$GLOBALS += [];
$GLOBALS =& $x;
$x =& $GLOBALS;
unset($GLOBALS);
Кроме того, передача $GLOBALS по ссылке будет вызывать ошибку времени выполнения:
by_ref($GLOBALS); # Ошибка времени выполнения
Я проанализировал 2000 самых популярных пакетов на Packagist и обнаружил только 23 случая, на которые повлияет это изменение. Можно сделать вывод, что влияние этого формально критического изменения будет незначительным, поэтому было решено добавить его в PHP 8.1. Следует отметить, что большая часть разработчиков от этого только выиграет, поскольку оно положительно повлияет на производительность кода.
Переход от ресурсов к объектам
Эти изменения являются частью долгосрочной стратегии преобразования всех ресурсов в выделенные объекты. Подробнее об этом можно прочитать здесь.
Функции Fileinfo и объекты finfo
Такие функции, как finfo_file и finfo_open, ранее принимали и возвращали ресурсы. Начиная с PHP 8.1 они работают с объектами finfo.
Функции IMAP и объекты IMAPConnection
Как и в случае функций Fileinfo, функции IMAP, такие как imap_body и imap_open, больше не работают с ресурсами.
Запрещена передача null в не поддерживающие null аргументы внутренних функций rfc
Суть изменения проста: внутренние функции в настоящее время принимают null в качестве аргументов, которые не могут иметь значение null, а данный RFC запрещает такое поведение. Например, сейчас возможен такой вызов:
str_contains("string", null);
В PHP 8.1 при вызовах такого рода будет выдаваться предупреждение об их упразднении (deprecation), а в PHP 9 эти предупреждения станут ошибками типизации.
Мелкие изменения
С каждым выпуском в язык вносится множество небольших изменений. Все они перечислены в руководстве UPGRADING на GitHub — обязательно ознакомьтесь с ним, если хотите знать о таких мелочах.
Вот сводка наиболее существенных изменений:
MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH больше не работает.
MYSQLI_STORE_RESULT_COPY_DATA больше не работает.
PDO::ATTR_STRINGIFY_FETCHES теперь работает и с логическим типом данных (boolean).
При использовании эмулированных подготовленных операторов целые числа и числа с плавающей запятой в наборах результатов PDO MySQL и SQLite будут возвращаться с использованием собственных типов PHP вместо строк.
Такие функции, как htmlspecialchars и htmlentities, теперь будут по умолчанию преобразовывать символ ' в '; некорректные данные в кодировке UTF-8 также будут заменяться символом Юникода, а не пустой строкой.
В функции hash, hash_file и hash_init добавлен новый аргумент $options; по умолчанию он имеет значение [], так что это не повлияет на уже написанный код.
Добавлена поддержка MurmurHash3 и xxHash.
На этом пока все. Я собираюсь регулярно обновлять эту статью в течение года, поэтому оформите подписку, если хотите быть в курсе.