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

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

PHP 2898 ~ 2 мин.

В 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 63
  • Заметки 13
  • Nginx 2
  • ИТ новости 2
  • Безопасность 2
  • Флуд 1
  • Видео 1
  • Docker 1
  • Roadmap 1
  • Архитектура 0

Хочешь слона?

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

sergeymukhin.com

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

Релизы PHP 8.3

Дата Релиз
8 Июня 2023 Альфа 1
22 Июня 2023 Альфа 2
6 Июля 2023 Альфа 3
18 Июля 2023 Feature freeze
20 Июля 2023 Бета 1
03 Августа 2023 Бета 2
17 Августа 2023 Бета 3
31 Августа 2023 RC 1
14 Сентября 2023 RC 2
28 Сентября 2023 RC 3
12 Октября 2023 RC 4
26 Октября 2023 RC 5
9 Ноября 2023 RC 6
23 Ноября 2023 GA

Что нового?