Здесь мы разберем, что нового появилось в php версии 8.1. Напомню, 24 ноября 2021 года на сайте php.net появилось уведомление о выходе PHP 8.1.0. Это последний второстепенный выпуск, в котором разработчики существенно увеличили производительность языка и добавили множество новых функций.
-
Запись вебинара (разбор всех новвведений тут): https://youtu.be/xKNMs4eWChE
-
Все нововведения перечислены тут, на русском: https://www.php.net/releases/8.1/ru.php
-
Скоро стартует курс по профессиональной разработке на php (уровень middle/senior) от Otus: https://fas.st/wRyRs
/**/
Популярность версий php
Список ключевых нововведений:
О каждом подробнее ниже …
Новые фишки php 8.1
Перечисления
class Status { const DRAFT = 'draft'; const PUBLISHED = 'published'; const ARCHIVED = 'archived'; } function acceptStatus(string $status) {...}
enum Status { case Draft; case Published; case Archived; } function acceptStatus(Status $status) {...}
Используйте перечисления вместо набора констант, чтобы валидировать их автоматически во время выполнения кода.
Readonly-свойства
class BlogData { private Status $status; public function __construct(Status $status) { $this->status = $status; } public function getStatus(): Status { return $this->status; } }
class BlogData { public readonly Status $status; public function __construct(Status $status) { $this->status = $status; } }
Readonly-свойства нельзя изменить после инициализации (т.е. когда им было присвоено значение).
Они будут крайне полезны при реализации объектов типа VO и DTO.
Callback-функции как объекты первого класса
$foo = [$this, 'foo']; $fn = Closure::fromCallable('strlen');
$foo = $this->foo(...); $fn = strlen(...);
С помощью нового синтаксиса любая функция может выступать в качестве объекта первого класса. Тем самым она будет рассматриваться как обычное значение, которое можно, например, сохранить в переменную.
Расширенная инициализация объектов
class Service { private Logger $logger; public function __construct( ?Logger $logger = null, ) { $this->logger = $logger ?? new NullLogger(); } }
class Service { private Logger $logger; public function __construct( Logger $logger = new NullLogger(), ) { $this->logger = $logger; } }
Объекты теперь можно использовать в качестве значений параметров по умолчанию, статических переменных и глобальных констант, а также в аргументах атрибутов.
Таким образом появилась возможность использования вложенных атрибутов.
Пересечение типов
function count_and_iterate(Iterator $value) { if (!($value instanceof Countable)) { throw new TypeError('value must be Countable'); } foreach ($value as $val) { echo $val; } count($value); }
function count_and_iterate(Iterator&Countable $value) { foreach ($value as $val) { echo $val; } count($value); }
Теперь в объявлении типов параметров можно указать, что значение должно относиться к нескольким типам одновременно.
В данный момент пересечения типов нельзя использовать вместе с объединёнными типами, например, A&B|C.
Тип возвращаемого значения never
function redirect(string $uri) { header('Location: ' . $uri); exit(); } function redirectToLoginPage() { redirect('/login'); echo 'Hello'; // <- dead code }
function redirect(string $uri): never { header('Location: ' . $uri); exit(); } function redirectToLoginPage(): never { redirect('/login'); echo 'Hello'; // <- dead code detected by static analysis }
Функция или метод, объявленные с типом never, указывают на то, что они не вернут значение и либо выбросят исключение, либо завершат выполнение скрипта с помощью вызова функции die(), exit(), trigger_error() или чем-то подобным.
Окончательные константы класса
class Foo { public const XX = "foo"; } class Bar extends Foo { public const XX = "bar"; // No error }
class Foo { final public const XX = "foo"; } class Bar extends Foo { public const XX = "bar"; // Fatal error }
Теперь константы класса можно объявить как окончательные (final), чтобы их нельзя было переопределить в дочерних классах.
Явное восьмеричное числовое обозначение
016 === 16; // false because `016` is octal for `14` and it's confusing 016 === 14; // true
0o16 === 16; // false — not confusing with explicit notation 0o16 === 14; // true
Теперь можно записывать восьмеричные числа с явным префиксом 0o.
Файберы
Код:
$httpClient->request('https://example.com/') ->then(function (Response $response) { return $response->getBody()->buffer(); }) ->then(function (string $responseBody) { print json_decode($responseBody)['code']; });
$response = $httpClient->request('https://example.com/'); print json_decode($response->getBody()->buffer())['code'];
Файберы — это примитивы для реализации облегчённой невытесняющей конкурентности. Они являются средством создания блоков кода, которые можно приостанавливать и возобновлять, как генераторы, но из любой точки стека. Файберы сами по себе не предоставляют возможностей асинхронного выполнения задач, всё равно должен быть цикл обработки событий. Однако они позволяют блокирующим и неблокирующим реализациям использовать один и тот же API.
Файберы позволяют избавиться от шаблонного кода, который ранее использовался с помощью Promise::then()
или корутин на основе генератора. Библиотеки обычно создают дополнительные абстракции вокруг файберов, поэтому нет необходимости взаимодействовать с ними напрямую.
Поддержка распаковки массивов со строковыми ключами
$arrayA = ['a' => 1]; $arrayB = ['b' => 2]; $result = array_merge(['a' => 0], $arrayA, $arrayB); // ['a' => 1, 'b' => 2]
$arrayA = ['a' => 1]; $arrayB = ['b' => 2]; $result = ['a' => 0, ...$arrayA, ...$arrayB]; // ['a' => 1, 'b' => 2]
PHP раньше поддерживал распаковку массивов с помощью оператора …, но только если массивы были с целочисленными ключами. Теперь можно также распаковывать массивы со строковыми ключами.
Что еще …
Новые классы, интерфейсы и функции
-
Добавлен новый атрибут
#[ReturnTypeWillChange]
-
Добавлены функции
fsync и fdatasync.
-
Добавлена новая функция
array_is_list.
-
Новые функции
Sodium XChaCha20.
Функция fsynk
<?php // Fsynk $file = fopen("sample.txt", "w"); fwrite($file, "Some content"); if (fsync($file)) { print("File save OK"); } fclose($file);
Улучшения производительности
Выигрыш в памяти
Нет Ответов