Здесь мы разберем, что нового появилось в php версии 8.1. Напомню, 24 ноября 2021 года на сайте php.net появилось уведомление о выходе PHP 8.1.0. Это последний второстепенный выпуск, в котором разработчики существенно увеличили производительность языка и добавили множество новых функций.

/**/

Популярность версий 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);

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

Выигрыш в памяти

Tags

Нет Ответов

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

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

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

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

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

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

Рубрики


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

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