Главная | Все статьи | Код

Вышел PHP 8.2: разбираем главные изменения

PHP Время чтения статьи ~11 минут
Вышел PHP 8.2: разбираем главные изменения главное изображение

Вместе с PHP-разработчиками Александром Макаровым, Валентином Удальцовым и наставником Хекслета по PHP Владленом Гилязетдиновым разбираемся, какие новые фичи появились в PHP 8.2, насколько эти изменения глобальны и какую роль в них сыграл проект РHP Foundation.

Эта статья — саммари стрима YouTube-канала PHP Point

Главные изменения в PHP 8.2

Readonly-классы

Поля readonly сделали еще до версии 8.2. Раньше писать в них код и читать его можно было только в конструкторе. А теперь для этого не нужно помечать каждое поле — достаточно отметить весь класс как readonly.

Как выглядел код в предыдущих версиях PHP:

class BlogData
{
    public readonly string $title;

    public readonly Status $status;

    public function __construct(string $title, Status $status)
    {
        $this->title = $title;
        $this->status = $status;
    }
}

Как выглядит код в PHP 8.2:

readonly class BlogData
{
    public string $title;

    public Status $status;

    public function __construct(string $title, Status $status)
    {
        $this->title = $title;
        $this->status = $status;
    }
}

Но у фичи есть особенности:

  1. Readonly-классы недоступны для классов с необъявленными типами
  2. Также readonly-классы недоступны для классов со статическими свойствами
  3. Если мы захотим наследоваться от старого readonly-класса, новый тоже должен быть Readonly

Изучите классы PHP на Хекслете Пройдите наш курс «PHP: Погружаясь в классы», чтобы узнать о позднем связывании, трейтах и абстрактных классах, а также понять, как устроено ООП внутри PHP.

Типы в виде дизъюнктивной нормальной формы (ДНФ)

Теперь вместо того, чтобы указывать тип mixed для аргументов в методах, можно просто перечислять необходимые типы через амперсанд.

Как выглядел код в предыдущих версиях PHP:

class Foo {
    public function bar(mixed $entity) {
        if ((($entity instanceof A) && ($entity instanceof B)) || ($entity === null)) {
            return $entity;
        }

        throw new Exception('Invalid entity');
    }
}

Как выглядит код в PHP 8.2:

class Foo {
    public function bar((A&B)|null $entity) {
        return $entity;
    }
}

Пожелание от меня: будьте осторожны с этой фичей. Она позволяет много методов объединять в один. Если бы я программировал приложения, то так не делал бы. А вот во фреймворках она будет очень кстати, потому что иногда, ради красивой API, мы сознательно жертвуем такой вот правильностью — используем подход с mixed-типами в сигнатуре.

Самостоятельные типы null, false и true

Это изменение единогласно приняла вся команда разработчиков PHP, так как в ядре PHP есть методы, классы и функции, которые возвращают false или true.

Если у вас метод никогда не возвращает false, то теперь можно указать, что он возвращает true или значение. Или наоборот, null и значение, или false и значение. Фича удобная и делает язык немного строже.

Как выглядел код в предыдущих версиях PHP:

class Falsy
{
    public function almostFalse(): bool { /* ... */ *}

    public function almostTrue(): bool { /* ... */ *}

    public function almostNull(): string|null { /* ... */ *}
}

Как выглядит код в PHP 8.2:

class Falsy
{
    public function alwaysFalse(): false { /* ... */ *}

    public function alwaysTrue(): true { /* ... */ *}

    public function alwaysNull(): null { /* ... */ *}
}

Модуль «Random»

Random — это целый пак разных интерфейсов. Особенности фичи:

  1. Разработчики сделали объектно-ориентированный API
  2. Каждый инстанс независимый — то есть для разных целей можно инстанцировать n-штук псевдослучайных генераторов, которые никогда не пересекутся. Стало более безопасно.
  3. Mersenne twister заменен на интерфейс Engine. Раньше mt_rand() надо было инициализировать. Он был нужен не для всяких крипто-фич, а для того чтобы, например, сортировать массивы в случайном порядке. mt_rand() работал достаточно быстро, поэтому использовать его для утилитарных задач было неплохо. Теперь его заменили на интерфейс Engine, который предоставляет готовые реализации.

Как выглядит код в PHP 8.2:

use Random\Engine\Xoshiro256StarStar;
use Random\Randomizer;

$blueprintRng = new Xoshiro256StarStar(
    hash('sha256', "Example seed that is converted to a 256 Bit string via SHA-256", true)
);

$fibers = [];
for ($i = 0; $i < 8; $i++) {
    $fiberRng = clone $blueprintRng;
    // Xoshiro256**'s 'jump()' method moves the blueprint ahead 2**128 steps, as if calling
    // 'generate()' 2**128 times, giving the Fiber 2**128 unique values without needing to reseed.
    $blueprintRng->jump();

Константы в трейтах

Теперь можно объявлять константы внутри трейтов. Особенность фичи — нельзя получить доступ к константе через имя трейта, но можно через класс, который использует этот трейт.

Очень логичное изменение, на мой взгляд. Трейт сам по себе — это копипаст. Копипаст — штука опасная, но иногда полезная (у нас есть принцип «don't repeat yourself»). И трейт — это один самых неинвазивных способов что-то повторить, который легко потом отрефакторить.

Как выглядит код в PHP 8.2:

trait Foo
{
    public const CONSTANT = 1;
}

class Bar
{
    use Foo;
}

var_dump(Bar::CONSTANT); // 1
var_dump(Foo::CONSTANT); // Error

Динамические свойства объявлены устаревшими

В классах PHP можно было динамически присваивать значения свойствам, которые мы не объявили ранее, и эти свойства появлялись после классов.

Теперь так сделать нельзя — будет появляться Deprecation notice. Но если сильно нужно, динамическими свойствами можно пользоваться, если пометить класс аннотацией #[\AllowDynamicProperties]. В экземплярах stdClass динамические свойства по-прежнему можно использовать.

Как выглядел код в предыдущих версиях PHP:

class User
{
    public $name;
}

$user = new User();
$user->last_name = 'Doe';

$user = new stdClass();
$user->last_name = 'Doe';

Как выглядит код в PHP 8.2:

class User
{
    public $name;
}

$user = new User();
$user->last_name = 'Doe'; // Deprecated notice

$user = new stdClass();
$user->last_name = 'Doe'; // Still allowed

#[\SensitiveParameter]

Это маленькая, но очень классная фича, которая мельком упоминается в официальном анонсе.

Параметры в методах теперь можно обозначить как #[\SensitiveParameter]. Ниже в коде так отмечен параметр $secret, и в логах вместо значения параметра secret написано (Object(SensitiveParameterValue).

function sensitiveParametersWithAttribute(
    #[\SensitiveParameter]
    string $secret,
    string $normal
) {
    throw new Exception('Error!');
}
Exception: Error! in example.php:15
Stack trace:
#0 example.php(25): sensitiveParametersWithAttribute(Object(SensitiveParameterValue), 'normal')
#1 {main}

Считаю это изменение очень крутым, так как теперь у нас не будут утекать всякие ключи от API, пароли от базы. Команда разработчиков PHP практически единогласно проголосовала за эту фичу.

Читайте также: Язык программирования PHP: рейтинг, сферы применения, прогнозы экспертов

Какие еще изменения произошли

Расширение enum в константах

Раньше, чтобы использовать enum, надо было дублировать их значение. Это было очень неприятно: enum есть, а в объявлениях констант нельзя было из них что-то использовать. Теперь можно: новая фича уравнивает весь синтаксис. Классно, что язык эволюционирует в сторону удобства и большей консистентности.

const C = [self::B->value => self::B];

iterator_*() + iterables

Теперь можно передавать в методы iterator_*() тип \Traversables. Это просто замечательно, потому что раньше приходилось проверять, является ли аргумент объектом типа \Traversable, и если да, то надо было его конвертить. В PHP 8.2 можно больше не проводить эти проверки, что уменьшает количество кода и делает его более приятным и читаемым.

Расширена рефлексия

  • Можно узнать, анонимный ли методReflectionFunction::isAnonymous()
  • Можно узнать, есть ли у метода прототипReflectionMethod::hasPrototype()

Новые функции memory_reset_peak_usage

Функции сбрасывают статистику по пиковому использованию памяти. Это очень полезно для EventLoop на PHP, Roadrunner и Swoole — мы сможем скинуть потребляемую память после запроса и измерить ту, которая ушла конкретно на один запрос.

Что признали устаревшим или убрали

  • Интерполяция в строках вида ${}
  • Не рекомендуется использовать функции utf8_encode и utf8_decode
  • Функции strtolower и strtoupper теперь не учитывают локаль — это круто, потому что версии PHP, установленные в двух системах Linux, могут работать по-разному из-за выбранной дефолтной локали.
  • Убрали много форматов callable:
    • “self::method”
    • “parent::method”
    • “static::method”
    • [“self”, “method”]
    • [“parent”, “method”]
    • [“static”, “method”]
    • [“Foo”, “Bar::Method”]
    • [new Foo, “Bar::Method”]

Мое мнение — на PHP 8.2 определенно стоит переходить хотя бы из-за крутых улучшений синтаксиса. Он все еще делает код более читаемым и понятным. Также разработчики пофиксили разные мелкие баги, которые мы не упомянули, но их было много.

Читайте также: Почему PHP идеально подходит для веб-разработки

Какие изменения PHP 8.2 еще в разработке

Некоторые разработчики считают, что в новую версию PHP добавили очень мало изменений. На самом деле, в РHP 8.2 было много саппортных вещей: код вычищали, из него что-то убирали. Каждое изменение, которое вводили разработчики, непросто описать в фичах. Да и вряд ли всем будет интересно, какие куски кода рефакторили. Так что по объему работы релиз 8.2 не отличается от предыдущих релизов. Просто в нем чуть меньше фич.

Большие усилия к разработке версии 8.2 приложили ребята из PHP Foundation — проекта, который финансирует разработчиков, готовых контрибьютить в PHP.

PHP Foundation создали много известных компаний, среди которых JetBrains, Automattic, Laravel. Проект запустили 22 ноября 2021 года, и за год коллектив из десяти администраторов-добровольцев и шести разработчиков внесли почти половину коммитов в ядро языка PHP и расширения.

В новую версию языка PHP Foundation имплементировал readonly-классы, самостоятельные типы null, false и true, тип true, типы в виде дизъюнктивной нормальной формы и получение свойств перечислений в константных выражениях. Также он объявил интерполяцию в строках вида ${} устаревшей.

Документация по PHP 8.2 еще в разработке, и разработчик PHP Foundation Джордж П. Баньярд сейчас отслеживает прогресс в изменениях. Вместе с командой он обсуждает эти нововведения:

  • Автоматическая имплементация для enum Stringable
  • Ассиметричная видимость
  • Получение констант из класса
  • Более понятные ошибки Date/Time
  • Доработки по Readonly
  • Работа с инициализаторами произвольных статических переменных.

Помочь составить документацию может каждый из нас — это, как говорится, good first issue (несложные задачи, выполнить которые под силу новичкам).

Также PHP Foundation планирует выдвинуть на обсуждение новые изменения в будущем релизе PHP 8.3.

Станьте профессиональным PHP-разработчиком с нуля за 10 месяцев На Хекслете есть профессия «PHP-разработчик». Пройдите ее, чтобы изучить один из самых известных языков программирования, освоить популярные фреймворки и создать большое портфолио с проектами на GitHub.

Стать PHP-разработчиком

Рекомендуемые программы
профессия
от 6 300 ₽ в месяц
Разработка фронтенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 25 апреля
профессия
от 6 300 ₽ в месяц
Разработка веб-приложений на Django
10 месяцев
с нуля
Старт 25 апреля
профессия
от 6 183 ₽ в месяц
Ручное тестирование веб-приложений
4 месяца
с нуля
Старт 25 апреля
профессия
от 6 300 ₽ в месяц
Разработка приложений на языке Java
10 месяцев
с нуля
Старт 25 апреля
профессия
от 5 025 ₽ в месяц
новый
Сбор, анализ и интерпретация данных
9 месяцев
с нуля
Старт 25 апреля
профессия
от 6 300 ₽ в месяц
Разработка веб-приложений на Laravel
10 месяцев
с нуля
Старт 25 апреля
профессия
от 5 840 ₽ в месяц
Создание веб-приложений со скоростью света
5 месяцев
c опытом
Старт 25 апреля
профессия
от 9 900 ₽ в месяц
Разработка фронтенд- и бэкенд-компонентов для веб-приложений
16 месяцев
с нуля
Старт 25 апреля
профессия
от 6 300 ₽ в месяц
Разработка бэкенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 25 апреля
профессия
новый
Автоматизированное тестирование веб-приложений на JavaScript
8 месяцев
c опытом
в разработке
Старт 25 апреля
профессия
Верстка с использованием последних стандартов CSS
5 месяцев
с нуля
Старт в любое время