PHP 8: Constructor Property Promotion
A comprehensive guide on writing cleaner, shorter class constructors.
Introduction
If you have been a software engineer for a while, you know that software engineers love using scary names to describe simple things. The term constructor property promotion should not scare you because you might be using it in your codebase already without realizing it has a fancy name.
Here are the things you will achieve after reading this article.
- You will be able to refactor a PHP class to use constructor property promotion instead of using the default syntax used when setting class properties in the constructor function.
- You will know the different ways of accessing class properties after setting them using the constructor property promotion syntax.
- You will know the common mistakes that lead to errors when using the constructor property promotion syntax in your PHP class and how to avoid them.
Interested? Let's move π
Prerequisites
- A basic understanding of Object-Oriented Programming in PHP
- You must have PHP 8 installed to enjoy this feature in your code or project. Alternatively, you can test this feature on phpsandbox by selecting PHP8 as your preferred version
What is Constructor Property Promotion? π€
Constructor property promotion is a feature introduced in PHP 8 that allows values passed to a constructor to be automatically set as class properties without the need to write the assignment statement in the body of the constructor. For a better understanding of the concept, let's take a look at the way values were assigned to class properties before the introduction of the constructor property promotion feature in PHP8.
Before constructor property promotion π₯±
Before constructor property promotion was introduced, hereβs how you will typically set the
firstName
and lastName
properties passed to the Employee
class through the constructor.
<?php
class Employee
{
protected $firstName, $lastName;
public function __construct(string $firstName, string $lastName)
{
$this->firstName = $firstName;
$this->lastName = $lastName;
}
}
$employee = new Employee('Ibrahim', 'Alausa');
In the code above, we are declaring the properties firstName
and lastName
without any initial value. Then, in the body of the constructor, we set the firstName
and lastName
properties to the value passed to the constructor. In this example, that is Ibrahim as the value of the firstName
property and Alausa as the value of the lastName
property.
The new way for the cool programmers π
Now, let's rewrite the Employee
class to use constructor property promotion. Let's see what our code will look like in this case
<?php
class Employee
{
public function __construct(protected string $firstName, protected string $lastName)
{
}
}
$employee = new Employee('Ibrahim', 'Alausa');
That's it. Yes. Isn't this beautiful? Just in case your answer is NO well, that was a rhetorical question, my friend. It is beautiful.
What exactly is different
By adding an access modifier (protected, private, etc) to each parameter in the constructor, PHP understands that you are trying to βpromoteβ the constructor parameter to a class property.
Important points to note when working with constructor property promotion
1. Accessing class properties π
Within the constructor, promoted properties can be accessed with or without the $this
keyword since they are still within the function scope where they were declared. Let's see what our code will look like in this case
<?php
class Employee
{
public function __construct(protected string $firstName, protected string $lastName)
{
var_dump($firstName); Ibrahim βοΈ
var_dump($this->firstName); Ibrahim βοΈ
}
}
$employee = new Employee('Ibrahim', 'Alausa');
Run the code here to see for yourself.
However, once you are outside the constructor, you need to use the $this
keyword to access all promoted properties so that PHP understands that you are referring to the firstName
or lastName
property of the class and not an undefined variable or a variable that may have been declared using the same name.
<?php
class Employee
{
public function __construct(protected string $firstName, protected string $lastName)
{
}
public function getUndefinedFirstName()
{
var_dump($firstName); // Output: Undefined variable '$firstName' β
}
public function getWrongFirstName()
{
$firstName = 'John';
var_dump($firstName); // Output:John β
}
public function getFirstName()
{
var_dump($this->firstName); // Output:Ibrahim βοΈ
}
}
$employee = new Employee('Ibrahim', 'Alausa');
Run the code here to see for yourself.
2. You don't have to promote all constructor parameters. Mix 'em up π₯
Letβs assume that for some reason, we need to append Fname_
to every value passed to our Employee class as the first name and we want to do that cleanly. We donβt need to promote the firstName
property. Let's see what our code will look like in this case.
<?php
class Employee
{
protected $firstName;
public function __construct(string $firstName, protected string $lastName)
{
$this->firstName = "Fname_$firstName";
}
public function getFirstName()
{
var_dump($this->firstName); // Output:Fname_Ibrahim βοΈ
}
}
$employee = new Employee('Ibrahim', 'Alausa');
Run the code here to see for yourself.
3. You either want to promote a property or you don't. Make a choice π€¦ββοΈ
This means that you can't declare a class property above the constructor and still try to promote that property in the constructor parameter list. Let's see what our code will look like in this case. Remember, this will throw an error.
<?php
class Employee
{
protected $firstName;
public function __construct(protected string $firstName, protected string $lastName)
//Cannot redeclare Employee::$firstName β
{
$this->firstName = $firstName;
}
}
$employee = new Employee('Ibrahim', 'Alausa');
Run the code here to see for yourself.
4. You can set default values for promoted properties π
If one or more values in the constructor are optional, a default value can be set for that property. Let's see what our code will look like in this case.
<?php
class Employee
{
public function __construct(protected string $firstName, protected string $lastName='N/A')
{
}
public function getLastName()
{
var_dump($this->lastName); //Output: N/A βοΈ
}
}
$employee = new Employee('Ibrahim');
Run the code here to see for yourself.
Quick Recap
- The constructor property promotion feature only works with PHP8.0 and above.
- To promote a constructor parameter to a class property, the constructor parameter should have an access modifier like public, private, etc.
- Since the constructor parameters are both parameters and class properties, you can access the promoted properties in the constructor with or without the
$this
keyword. However, class properties must be accessed with thethis
keyword outside the constructor function. - Not all parameters need to be promoted. Mix 'em up and enjoy the best of both worlds.
- While trying to enjoy the best of both worlds, remember that you can't declare a class property above the constructor and still try to promote that property in the constructor parameter list.
- Default values can be set for promoted properties in the constructor.
It's a wrap π
PHP8 comes with a lot of amazing features that will make you write shorter and cleaner code. If you can, upgrade your version and start using it today.
Thanks for sticking with me till the end. If you have any suggestions or feedback, kindly drop them in the comment section. Enjoy the rest of your day...bye π.