Initialize objects right into the constructor parameters in PHP 8.1
With the introduction of PHP 8, the language now allows us to declare the class properties right into the constructor parameters. This is called constructor property promotion.
So, instead of doing so…
<?php
class Book
{
private string $name;
private string $author;
public function __construct(
string $name = 'The Alchemist',
string $author = 'Paulo Coelho'
) {
$this->name = $name;
$this->author = $author;
}
}
…you can do something like so.
class Book
{
public function __construct(
private string $name = 'The Alchemist',
private string $author = 'Paulo Coelho'
) {}
}
This brings the following benefits to our disposal.
-
There’s no need to declare properties in the class and defining them into the constructor body.
-
The syntax is shorter and less error-prone as you don’t have to maintain the same property at three different places!
This is nice but you still can’t directly initialize an object if there’s a need. This is what PHP 8.1 attempts to solve.
Initializing objects in constructor properties
This RFC for PHP 8.1 proposes to allow the use of new expressions inside…
- Parameter default values
- Attribute arguments
- Static variable initializers
- Global constant initializers
The functionality is a further refinement of PHP 8’s constructor property promotion.
What this essentially means is the code that you used to write pre PHP 8.1…
class Test
{
private Logger $logger;
public function __construct(
?Logger $logger = null,
) {
$this->logger = $logger ?? new NullLogger;
}
}
…Can now be written like this.
class Test
{
public function __construct(
private Logger $logger = new NullLogger,
) {}
}
As you can tell, here, in this case, the default null
value is also handled implicitly as opposed to what you would do pre PHP 8.1.
Pretty concise, right?
It is possible to pass arguments to the constructor, including the use of named arguments like so.
function test(
$foo = new A,
$bar = new B(1),
$baz = new C(x: 2),
) {
}
Restrictions
There are, however, some restrictions as well.
The use of…
- A dynamic or non-string class name or an anonymous class is not allowed.
- Argument unpacking is not allowed.
- Unsupported expressions as arguments are not allowed.
So, the following is not possible.
function test(
$a = new (CLASS_NAME_CONSTANT)(), // dynamic class name
$b = new class {}, // anonymous class
$c = new A(...[]), // argument unpacking
$d = new B($abc), // unsupported constant expression
) {}
In closing
The inclusion of these new initializers in the constructor properties makes the already awesome constructor property promotion better and provides a fantastic developer experience!
Like this article?
Buy me a coffee👋 Hi there! I'm Amit. I write articles about all things web development. You can become a sponsor on my blog to help me continue my writing journey and get your brand in front of thousands of eyes.