This article is a translation, original address: https://stitcher.io/blog/php-81-new-in-initializers
PHP 8.1: Initializer ( new in initializers)
PHP 8.1 adds a seemingly small detail, but I think it will have a significant day-to-day impact on many people. So what is this "What's new in the Initializer RFC" about? Let's look at an example; we've all written code like this:
class MyStateMachine { public function __construct( private ?State $state = null, ) { $this->state ??= new InitialState(); } }
In this state machine example, we want to structure our class in two ways: with and without an initial state. If we build it without an initial state, we want to set a default state. PHP certainly supports setting initial values directly in the parameter list, but only for primitive types. For example, if our state machine uses strings internally instead of objects, we can write its constructor like this:
class MyStateMachine { public function __construct( private string $state = 'initial', ) { } }
So, in PHP 8.1, we can also use the same " Default value" syntax. In other words: you can use new default parameters (this is an example of an "initializer"):
class MyStateMachine { public function __construct( private State $state = new InitialState(), ) { } }
An "initializer" is not just a parameter default, here's a simple explanation from the RFC:
This RFC proposes to allow new expressions in parameter default values, property parameters, static variable initializers, and global constant initializers
You read that right: properties also On this list! Imagine a simple validation library that uses attributes to validate input to properties. Maybe it should be able to validate array elements like this:
class CreateEmailsRequest extends FormRequestData { #[ValidArray( email: [new Required, new ValidEmail], name: [new Required, new ValidString], )] public array $people; }
Before PHP 8.1 you wouldn't be able to write such code because you were not allowed to use new in attributes due to the way they were evaluated, but now There you go!
Let’s take a look at some important details worth mentioning.
Do you want to know more about PHP 8.1? There is a path to PHP 8.1. For the next 10 days, you will receive a daily email about a new and existing feature of PHP 8.1; you will then be automatically unsubscribed so you won't receive spam or follow-up emails. Subscribe now!
#Build only when needed
These "new values" will only be built when actually needed. This means that, in our first example, InitialState will only create a new object if no arguments are given:
class MyStateMachine { public function __construct( private State $state = new InitialState(), ) { } } new MyStateMachine(new DraftState()); // No InitialState is created new MyStateMachine(); // But now it is
For example, in the case of properties, only newInstance will be called when called on a reflective property The object will be created.
#Not in a class attribute
You should also know that new cannot be used as a default value in a class attribute. Supporting this feature introduces a number of unforeseen side effects, for example, when serializing and deserializing objects.
class MyStateMachine { private State $state = new InitialState(); }
Fortunately, we hoisted properties that allowed default values, because PHP will convert the property hoisting syntax to retain the default value in the constructor parameter, but not in the actual property.
The following is the translated version:
class MyStateMachine { private State $state; public function __construct( State $state = new InitialState(), ) { $this->state = $state; } }
#Limited Input
You may have guessed it, but constructing new objects in the initializer , you can only pass a limited set of inputs. For example, you cannot use variables, spread operators, anonymous classes, etc. Still, it's a very welcome addition!
The above is the detailed content of PHP8.1 new features explained initializers initializer. For more information, please follow other related articles on the PHP Chinese website!