PHP 4187 ~ 2 мин.

PHP 8.1: оператор new в инициализаторах

PHP 8.1: оператор new в инициализаторах

В PHP 8.1 добавлена интересная ​​функция, которая на первый взгляд может показаться мелочью, но я думаю, что она будет оказывать значительное повседневное влияние на многих людей.

Так в чем же польза от  оператора new в инициализаторах? Давайте посмотрим на пример, раньше мы все писали такой код:


class MyStateMachine
{
    public function __construct(
        private ?State $state = null,
    ) {
        $this->state ??= new InitialState();
    }
}

В этом примере с конечным автоматом мы хотели бы построить наш класс двумя способами: с начальным состоянием и без него. Если мы построим его без начального состояния, мы хотим, чтобы было установлено состояние по умолчанию. PHP,  конечно, поддерживает установку начальных значений непосредственно в списке параметров, но только для примитивных типов. Например, если бы наш конечный автомат использовал строки вместо объектов внутри, мы могли бы написать его конструктор следующим образом:


class MyStateMachine
{
    public function __construct(
        private string $state = 'initial',
    ) {
    }
}

Таким образом, с PHP 8.1 мы можем использовать тот же синтаксис «значения по умолчанию» и для объектов. Другими словами: вы можете использовать new для аргументов по умолчанию (которые являются одним из примеров «инициализаторов»): 


class MyStateMachine
{
    public function __construct(
        private State $state = new InitialState(),
    ) {
    }
}

 «Инициализаторы» - это больше, чем значения параметров по умолчанию, вот простое объяснение из RFC:

Этот RFC предлагает разрешить использование новых выражений внутри значений параметров по умолчанию, аргументов атрибутов, инициализаторов статических переменных и инициализаторов глобальных констант.

Да, вы правильно прочитали: атрибуты тоже есть в этом списке! Представьте себе простую библиотеку проверки, которая использует атрибуты для проверки ввода свойств. Возможно, она должна иметь возможность проверять элементы массива, примерно так:


class CreateEmailsRequest extends FormRequestData
{
    #[ValidArray(
        email: [new Required, new ValidEmail],
        name: [new Required, new ValidString],
    )]
    public array $people;
}

До PHP 8.1 вы не могли писать такой код, потому что вам не разрешалось использовать new в атрибутах из-за способа их оценки, но теперь вы можете! 

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

Создание только при необходимости

Такого рода «новые значения» будут создаваться только тогда, когда это действительно необходимо. Это означает, что в нашем первом примере PHP создаст только новый объект, если InitialState не содержит аргументов:


class MyStateMachine
{
    public function __construct(
        private State $state = new InitialState(),
    ) {
    }
}

new MyStateMachine(new DraftState()); // InitialState не создается
new MyStateMachine(); // Сейчас создается

В случае атрибутов, например, объекты будут созданы только при newInstance вызове атрибута отражения

Не в свойствах класса

Также вы должны знать, что не можете использовать new значение по умолчанию в свойствах класса. Поддержка этой функции привела бы к множеству непредвиденных побочных эффектов, например, при сериализации и десериализации объектов:


class MyStateMachine
{
    private State $state = new InitialState();
}

Сначала кажется, что это большое упущение, но к счастью, это решается с помощью объявления свойства в конструкторе, которые допускают значение по умолчанию, поскольку PHP будет переносить синтаксис объявления свойств, сохраняя значение по умолчанию в аргументе конструктора, но не фактически в свойстве:


class MyStateMachine
{
    private State $state;
    
    public function __construct(
        State $state = new InitialState(),
    ) {
        $this->state = $state;
    }
}

Ограниченный ввод

Возможно, вы уже догадались, но вы можете передать только ограниченный набор входных данных при создании новых объектов в инициализаторах. Например, вы не можете использовать переменные, оператор распаковки, анонимные классы и т.д.


Что думаешь?

Категории
  • PHP 68
  • Заметки 18
  • Безопасность 4
  • Флуд 2
  • Nginx 2
  • ИТ новости 2
  • Видео 1
  • Docker 1
  • Roadmap 1
  • Архитектура 0

Хочешь поддержать сайт?

Делаем из мухи слона

sergeymukhin.com

персональный блог о веб-разработке от Сергея Мухина. Блог был основан в 2018 году, и собирался уделять основное внимание последним тенденциям, учебным пособиям, а также советам и рекомендациям, позволяющим начинающим девелоперам встать быстрее на правильную дорогу веб разработки, но что-то пошло не так 😃

Релизы PHP 8.4

Дата Релиз
4 Июля 2024 Альфа 1
18 Июля 2024 Альфа 2
1 Августа 2024 Альфа 3
13 Августа 2024 Feature freeze
15 Августа 2024 Бета 1
29 Августа 2024 Бета 2
12 Сентября 2024 Бета 3
26 Сентября 2024 RC 1
10 Октября 2024 RC 2
24 Октября 2024 RC 3
7 Ноября 2024 RC 4
21 Ноября 2024 GA

Что нового?