PHP 8.1 в настоящее время находится в активной разработке и, вероятно, будет выпущен где-то в конце ноября 2021 года. Но мы уже знаем некоторые функции, изменения и устаревшие версии, поэтому давайте рассмотрим их уже сейчас. Имейте в виду, что этот список как и PHP 8 будет расти с годами. (1)

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

Как и другие выпуски PHP, PHP 8.1 добавит несколько приятных новых возможностей. Также звучим некоторые функции, которые еще не были реализованы, но у которых есть хорошие шансы появиться в конечном релизе PHP. (1)

Распаковка массива с помощью строковых ключей

Распаковка массива уже была разрешена в PHP 7.4, но работала только с числовыми ключами. Причина, по которой строковые ключи не поддерживались раньше, заключается в том, что не было единого мнения о том, как объединять дубликаты массивов. RFC четко решает эту проблему, следуя семантике array_merge:

$array = ["a" => 1];

$array2 = ["b" => 2];

$arrayMerge = ["a" => 0, ...$array, ...$array2];

var_dump($arrayMerge); // ["a" => 1, "b" => 2]

Новый тип возврата never

Тип never может быть использован для того, чтобы указать, что функция фактически остановит поток приложения. Это можно сделать, выбросив исключение, вызывая exit/die или используя другие подобные функции.

function redirect(string $url): never {
    header('Location: ' . $url);
    exit();
}

redirect('Test'); // код гарантирует не продолжение.

do_something_else();

Тип возвращаемого значения never аналогичен существующему типу возвращаемого значения void, но тип never гарантирует, что программа завершится или выдаст исключение. Другими словами, объявленная функция/метод never типом вообще не должна вызывать return.

function foo(): never {
    return;
}

foo();

TypeError: dispatch(): Nothing was expected to be returned

Как видите, если функция/метод с типом never никак не сгенерирует исключение, или прекратит работу, то PHP выдаст исключение TypeError.

А если при never типе вызвать return, то PHP выдаст Fatal Error. Узнать об этом можно будет только во время вызова, а не во время синтаксического анализа.

function foo(): never {
    return;
}

foo();

Fatal error: A never function must not return in … on line 2

Исходный RFC предлагал использовать noreturn для этой цели. Впрочем последующее голосование в RFC прошло уже в пользу never и он был избран.

Новая функция array_is_list

Возможно, время от времени, вам приходится иметь с этим дело: определять, находятся ли ключи массива в числовом порядке, начиная с индекса 0. Точно так же, как 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

Любой массив с ключами, не начинающимися с нуля, или любой массив, в котором не все ключи являются целыми числами в последовательном порядке, результат будет false:

// ключи начинаются не с 0
array_is_list([1 => 'apple', 'orange']); // false

// Ключи не отсортированы
array_is_list([1 => 'apple', 0 => 'orange']); // false

// Не все числовые ключи
array_is_list([0 => 'apple', 'foo' => 'bar']); false

// Непоследовательные ключи
array_is_list([0 => 'apple', 2 => 'bar']); false

array_is_list принимает только параметры типа array. Передача любого другого типа вызовет исключение TypeError.

array_is_list не принимает iterable или другие объекты класса, подобные массиву, такие как ArrayAccess, SPLFixedArray и т.д.

array_is_list объявлен в глобальном пространстве имен.

(звезда) Полифил функции будет выглядеть, как:

function array_is_list(array $array): bool {
    if (empty($array)) {
        return true;
    }

    $current_key = 0;

    foreach ($array as $key => $noop) {
        if ($key !== $current_key) {
            return false;
        }
        ++$current_key;
    }

    return true;
}

Явное восьмеричное целочисленное буквальное обозначение

Теперь вы можете использовать 0o (нуль и маленькая буква o) и 0O (нуль и большая буква O) для обозначения восьмеричных чисел. Предыдущее обозначение с префиксом числа «0» по-прежнему работает:

016 === 0o16; // true

016 === 0O16; // true

Enums (Перечисления)

Перечисления будут добавлены в PHP 8.1.

Добавление перечислений было бы значительным улучшением в PHP.

Чтобы вы могли быстро увидеть, как они будут выглядеть, вот пример кода:

enum Status {
  case Pending;
  case Active;
  case Archived;
}

// И вот как они будут использоваться:
class Order
{
    public function __construct(
        private Status $status = Status::Pending;
    ) {}

    public function setStatus(Status $status): void
    {
        // …
    }
}

$order->setStatus(Status::Active);

Fibers

Файберы — также известные как «зеленые потоки» — это низкоуровневый механизм управления параллелизмом. Вероятно, вы не будете использовать их непосредственно в своих приложениях, но такие фреймворки, как Amphp и ReactPHP, будут широко их использовать.

Вот простой пример использования файберов:

$fiber = new Fiber(function (): void {
    $valueAfterResuming = Fiber::suspend('after suspending');
    // … 
});

$valueAfterSuspending = $fiber->start();

$fiber->resume('after resuming');

Улучшения производительности

Дмитрий Стогов добавил некоторые улучшения в opcache, он называет это «кешем наследования».

Эта функция позволяет кэшировать ссылки между классами, так же как связанные классы могут быть предварительно загружены в PHP 7.4.

Дмитрий сообщает о приросте производительности от 5% до 8% благодаря этому изменению, приятная небольшая деталь, на которую следует обратить внимание в PHP 8.1.


Критические изменения

Хотя PHP 8.1 является последующей версией после PHP 8, все же будут внесены некоторые изменения, которые технически могут быть критическими, а также устаревшими. Давайте обсудим их по очереди.

Ограничить использование $GLOBALS

Небольшое изменение способа использования $GLOBALS существенно повлияет на производительность всех операций с массивами. Никита Попов отлично справляется с объяснением проблемы и решения в RFC . Это изменение означает, что в некоторых крайних случаях работать с $GLOBAL больше нельзя.

«То, что больше не поддерживается, — это запись в $GLOBALS, взятую как единое целое».

Все нижеперечисленное вызовет ошибку времени компиляции:

$GLOBALS = [];

$GLOBALS += [];

$GLOBALS =& $x;

$x =& $GLOBALS;

unset($GLOBALS);

Кроме того, передача $GLOBALS по ссылке вызовет ошибку времени выполнения:

by_ref($GLOBALS); // Run-time error

Никита проанализировал 2000 лучших пакетов на сайте packagist и нашел только 23 случая, на которые повлияет это изменение. Можно сделать вывод, что влияние этого технически критического изменения будет незначительным, поэтому internals решили добавить его в PHP 8.1. Помните, что большинство из нас выиграет от этого изменения, учитывая положительное влияние на производительность, которое оно оказывает во всем нашем коде.

Перенос Ресурсов в объекты

Эти изменения являются частью долгосрочного видения преобразования всех ресурсов в выделенные объекты. Вы можете прочитать об этом здесь.

Fileinfo функции с объектами finfo. Функции вроде finfo_file и finfo_open используются для приема и возврата ресурсов. Начиная с PHP 8.1, они работают с объектами finfo.

Функции IMAP с объектами IMAPConnection. Как и при изменении информации о файле, IMAP работает как imap_body, а imap_open больше не работает с ресурсами.

Устарела передача null не null-ых аргументов внутренним функциям

Это изменение простое: внутренние функции в настоящее время принимают null аргументы, которые не допускают значения NULL, этот RFC не рекомендует такое поведение. Например, сейчас это возможно:

str_contains("string", null);

В PHP 8.1 такие ошибки будут вызывать предупреждение об устаревании, в PHP 9 они будут преобразованы в ошибки типа.

Другие небольшие изменения

Вот краткое изложение наиболее значительных изменений:

  • MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH больше не действует

  • MYSQLI_STORE_RESULT_COPY_DATA больше не действует

  • PDO::ATTR_STRINGIFY_FETCHES теперь также работает с логическими значениями

  • Целые числа и числа с плавающей запятой в наборах результатов PDO MySQL и Sqlite будут возвращаться с использованием собственных типов PHP вместо строк при использовании эмулированных подготовленных операторов.

  • Такие функции, как htmlspecialchars и htmlentities по умолчанию, также переходят ‘в ‘; неверно сформированный UTF-8 также будет заменен символом Юникода вместо того, чтобы приводить к пустой строке

  • У hash, hash_file и hash_init есть дополнительный аргумент $options, по умолчанию он имеет значение [], поэтому не повлияет на ваш код.

  • Новая поддержка для MurmurHash3 и xxHash


Источники:

(1) Блог Сергея Мухина: https://sergeymukhin.com/blog/chto-novogo-v-php-81

Tags

Нет Ответов

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Рубрики


Подпишись на новости
👋

Есть вопросы?