Backend Development

Constructor Property Promotion In PHP 8.0

Constructor Property Promotion In PHP 8

Constructor Property Promotion is a feature in PHP 8.0 related to constructor arguments. Let’s see this feature in this article. 

 

 

To describe the Class Constructor Property Promotion in PHP look at this example:

<?php

class Product
{
    public int $id;
    public string $name;
    public float $price;

    function __construct(int $id, string $name, float $price)
    {
         $this->id = $id;
         $this->name = $name;
         $this->price = $price;
    }
}

In this class we have three properties for the product, ($id, $name, $price). The constructor also accepts these argument so whenever creating any instance of this class you have to provide these arguments. This is a common example we usually see a lot. 

By using the Constructor Property Promotion we can rewrite this example in a simple way:

<?php

class Product
{
    function __construct(public int $id, public string $name, public float $price)
    {
    }
}

As shown in the code the Property Promotion feature allow us to do class property declaration and property assignment right from the constructor. So this code is pretty similar to the original code. This enables us shorten big classes that contain many properties. 

 

How this works?

Typically when a constructor argument includes a modifier such as public, private, protected, etc, PHP interpreter will interpret it as an object property and a constructor argument, then assign the argument value to the property. 

Note that this feature from PHP 8.0 and later so you can’t use it in PHP < PHP 8.0

 

Promoted Property & Modifiers

So to make a class property to be Promoted you have to provide a visibility modifier (public, private, protected) in front of it like so:

Example 1:

class User {
      function __construct(public string $username) {}
}
$user = new User('John');
echo $user->username;

Example 2:

class Product
{
    function __construct(private int $id, public string $name, protected float $price)
    {
    }

    function getId()
    {
    	return $this->id;
    }

    function getPrice()
    {
    	return $this->price;
    }
}

$product = new Product(2, "New Product", 100);
echo "Product ($product->name) #{$product->getId()} cost {$product->getPrice()}";

You can use also use the readonly modifier in PHP 8.1 to make the property promoted as shown:

class Product
{
    function __construct(private int $id, public string $name, readonly int $price)
    {
    }
}

 

Omitting the visibility modifier make the property unpromoted, therefore you have to initialize it the old way:

class User 
{ 
    public string $username;

    function __construct(string $username) 
    {
        $this->username = $username;
    } 
}

 

 

Mixing Promoted and Non Promoted Properties

You can mix the Constructor Promoted and Non-Promoted properties in a single constructor:

class Product
{
    public float $price;

    function __construct(public int $id, public string $name, float $price)
    {
    	$this->price = $price;
    }
}

$product = new Product(2, "New Product", 100);
echo $product->name . " with price (" . $product->price . ")";

As you see the $price property is a non-promoted property.

 

Not Allowed Duplicated Properties

You can’t declare a standard property and promoted property with the same name as this results in a fatal error:

class Product
{
    public float $price;

    function __construct(public int $id, public string $name, public float $price)
    {

    }
}
Fatal error: Cannot redeclare Product::$price in ....

 

You can remove type hints from properties

Type hints or typed properties isn’t required when using promoted properties although it’s better to type hint properties but it’s not a requirement as in this example: 

class User 
{ 
    function __construct(public $username) 
    {
    } 
}
$user = new User("Wael Salah");
echo $user->username;

 

Allowed in Traits

As PHP traits can contain constructors, methods and properties, so you can use Constructor Property Constructor as well:

trait ResponseTrait
{
    function __construct(public string $message, public int $statusCode)
    {}
}

 

Promoted Properties in Interfaces & Abstract Classes

Interfaces not support promoted properties, any attempt to use them it will trigger a fatal error:

interface PostType
{
    public function __construct(public array $params);
}
Fatal error: Cannot declare promoted property in an abstract constructor in ... 

In abstract classes promoted properties supported only if the constructor not marked as abstract:

abstract class PostType
{
    public function __construct(public array $params) {}   // Valid
}

If the abstract class constructor marked as abstract then promoted properties not allowed:

abstract class PostType
{
    abstract public function __construct(public array $params);   // Not Valid
}

Fatal error: Cannot declare promoted property in an abstract constructor

 

 

0 0 votes
Article Rating

What's your reaction?

Excited
0
Happy
0
Not Sure
0
Confused
1

You may also like

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments