Версия 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];
$array2 = ["b" => 2];
$array = ["a" => 0, ...$array1, ...$array2];
var_dump($array); // ["a" => 1, "b" => 2]
Новый тип never rfc
Тип never можно использовать для указания того, что функция будет останавливать поток выполнения программы. Это можно сделать вызовом исключения или функции exit
либо подобных ей.
function dd(mixed $input): never
{
// dump
exit;
}
never
отличается от void
тем, что void
позволяет программе продолжить выполнение. Этот тип может показаться необычным новшеством, но на деле он будет весьма полезен для статических анализаторов.
Новая функция array_is_list rfc
Возможно, вы имели дело с задачами, когда нужно было определить, представляют ли ключи массива числовую последовательность 0, 1, 2, 3..., подобно тому, как функция json_encode определяет, следует ли кодировать массив как массив или как объект.
В PHP 8.1 добавлена встроенная функция для определения того, является ли массив списком с такой семантикой или нет:
$list = ["a", "b", "c"];
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";
}
Начиная с PHP 8.1 такие константы можно помечать словом final
, чтобы исключить эту возможность:
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
.
На этом пока все. Я собираюсь регулярно обновлять эту статью в течение года, поэтому оформите подписку, если хотите быть в курсе. Вы рады скорому выходу PHP 8.1? Поделитесь своими ожиданиями со мной в Twitter!
Материал подготовлен в рамках курса "PHP Developer. Professional".
Всех желающих приглашаем на интенсив "Поговорим о тестировании" (День 2). На этом занятии мы:
— Поговорим про тестируемый код и о том как его писать;
— Освоим написание Unit-тестов с использованием PHPUnit;
— A-TRIP, TDD и Red-Green-Refactor;
— Посмотрим на идеологию CI/CD и запуск автоматического прогона наших тестов в Travis.
К концу занятия научимся писать правильные Unit-тесты. РЕГИСТРАЦИЯ