Constructor Property Promotion in PHP 8
Constructor property promotion is one of the greatest new features introduced in PHP 8. This new feature allows you to write cleaner and shorter class constructors by declaring and assigning class properties directly in one place inside the __construct() method.
Before PHP 8, developers had to follow a longer syntax to declare class properties and assign values inside the constructor. With PHP 8, this process becomes simpler, more readable, and less error-prone.
Why Constructor Property Promotion in PHP?
Before PHP 8, to write class constructors, we usually required:
- Declaring class properties separately.
- Accepting parameters inside the constructor.
- Assigning constructor parameters to class properties manually.
This leads to duplicate code, especially in large classes.
Example (Before PHP 8):
class Person {
private string $name;
private int $age;
public function __construct(string $name, int $age) {
$this->name = $name;
$this->age = $age;
}
}
In this example, we have defined the class properties $name and $age separately at the top of the class, and then assigned values to them manually inside the constructor using $this->name and $this->age. This means:
1. Properties are declared first:
private string $name; private int $age;
2. Constructor accepts parameters:
public function __construct(string $name, int $age)
3. Properties are manually assigned inside the constructor:
$this->name = $name; $this->age = $age;
This is the traditional way of writing constructors before PHP 8.
PHP 8 solved this by introducing a powerful feature — constructor property promotion. It allows you to declare and assign properties directly inside the constructor parameters, reducing the length of code and making classes more concise.
Basic Syntax of Constructor Property Promotion
The basic syntax to declare a constructor with property promotion is as:
class ClassName {
public function __construct(
// Property declaration and assignment happen here.
public Type $propertyName1,
protected Type $propertyName2,
private Type $propertyName3
) {
// Optional code block
}
}
Let’s modify the previous example to see how it would look when using constructor property promotion.
<?php
class Person {
public function __construct(
private string $name = "Saanvi",
private int $age = 18
) {}
public function displayInfo(){
echo "Name: " . $this->name . "\n";
echo "Age: " . $this->age;
}
}
// Create an object of class Person.
$person = new Person();
// Calling method using object reference variable.
$person->displayInfo();
?>
Output:
Name: Saanvi Age: 18
As you can see, there are several benefits of using constructor property promotion. They are:
- No need to declare properties separately in the class and then define them inside the constructor body.
- No need to write $this->property = $value; manually.
- The syntax is shorter, cleaner, and less error-prone.
How Constructor Property Promotion Works?
When you use visibility keywords (such as public, private, or protected) inside the constructor parameter list, PHP automatically:
- Declares the property inside the class.
- Assigns the passed value to that property.
Only the parameters that have visibility keywords are promoted to class properties. Parameters without visibility keywords are not promoted.
Rules of Using Constructor Property Promotion in PHP 8
There are some important rules you must remember while using Constructor Property Promotion in PHP 8:
- You can use constructor property promotion only inside the class constructor __construct(), not in any other class methods.
- You cannot use it in non-class-based methods.
- You can use promoted properties inside abstract class constructors. But, you cannot do inside interfaces, because interfaces have no properties or constructor body.
- Properties with callable types cannot be promoted.
- If the property is nullable, you must explicitly declare the nullability using ?. For example:
public function __construct(private ?string $name) {}- Variadic parameters (…$values) cannot be promoted, so the following code is invalid:
public function __construct(private ...$data) {}- Promoted and non-promoted parameters can be used together, so the following code is absolutely valid.
public function __construct(
private string $name, // Promoted
private int $age, // Promoted
$country // Non-promoted
) {}
Which Parameters are Promoted and Not Promoted?
A parameter becomes a promoted property ONLY IF:
- It is inside __construct() method.
- It has a visibility keyword (such as public, private, and protected).
- It has a type declaration.
Otherwise, parameters are not promoted.
Examples of Constructor Property Promotion
Let’s take some important examples based on the constructor property promotion introduced in PHP 8.
Example 1: Basic
<?php
class Product {
public function __construct(
public string $title,
public float $price
) {}
}
$product = new Product("Laptop", 55000.50);
echo $product->title . "\n";
echo $product->price;
?>
Output:
Laptop 55000.5
Example 2:
<?php
class Student {
// Properties are declared and initialized in one line.
public function __construct(
public string $name,
public int $age,
public string $course
) {}
public function displayInfo() {
echo "Name: $this->name<br>";
echo "Age: $this->age<br>";
echo "Course: $this->course<br>";
}
}
$student = new Student("John", 22, "BCA");
$student->displayInfo();
?>
Output:
Name: John Age: 22 Course: BCA
When we use the visibility keyword, such as public, protected, or private before the constructor parameters, PHP automatically declare and assign those parameters as class properties. You do not need to manually declare $this->property = $property;.
Example 3: With Visibility Control
You can use different access modifiers with the constructor parameters.
<?php
class Employee {
public function __construct(
private string $name,
protected string $department,
public float $salary
) {}
public function showDetails() {
echo "Name: $this->name \n";
echo "Department: $this->department \n";
echo "Salary: $this->salary";
}
}
$emp = new Employee("Alice", "HR", 55000);
$emp->showDetails();
?>
Output:
Name: Alice Department: HR Salary: 55000
Example 4: Nullable Property Promotion
Here is a simple example of using nullable types with Constructor Property Promotion in PHP 8:
<?php
class Student {
public function __construct(
private string $name,
private ?string $email = null
) {}
public function showInfo() {
echo "Name: {$this->name} \n";
echo "Email: " . ($this->email ?? "Not provided");
}
}
$student1 = new Student("Deepak", "deepak@gmail.com");
$student1->showInfo();
echo "\n \n";
$student2 = new Student("Saanvi"); // No email passed
$student2->showInfo();
?>Output:
Name: Deepak Email: deepak@gmail.com Name: Saanvi Email: Not provided
In this example,
- ?string means the property can store either a string or null.
- $email = null makes it optional.
If no value is passed, $email becomes null.
Example 5: Read-Only Properties in PHP 8.1
<?php
class Order {
public function __construct(
public readonly int $orderId,
public readonly float $amount,
public readonly string $status = "Pending"
) {}
}
$order = new Order(101, 2500.50);
echo $order->orderId . "\n"; // Allowed
echo $order->amount . "\n"; // Allowed
echo $order->status . "\n"; // Allowed
// Trying to modify readonly property.
// $order->status = "Completed"; // Fatal Error: Cannot modify readonly property.
?>
Output:
101 2500.5 Pending
In this example, we have declared class properties with readonly, which the property can only be written once inside constructor. After the object is created, you cannot modify the value. If you try to modify, you will get:
Fatal error: Cannot modify readonly property Order::$status
Can We Use Validation Inside Constructor?
Yes, we can use validation inside a constructor even when we are using Constructor Property Promotion in PHP 8. This is very useful when you want to ensure that invalid values are not assigned during object creation. Look at the example below.
Example 1: Validation Inside Constructor
<?php
class Student {
public function __construct(
private string $name,
private int $age
) {
if ($age < 5) {
throw new Exception("Age must be at least 5 years.");
}
if (strlen($name) < 3) {
throw new Exception("Name must be at least 3 characters long.");
}
}
public function showInfo() {
echo "Name: {$this->name}, Age: {$this->age}";
}
}
try {
$student = new Student("Al", 4); // Validation fails.
$student->showInfo();
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
?>Output:
Error: Age must be at least 5 years.
PHP first assigns values to the promoted properties and then executes the constructor body. Inside the constructor body, you can write any validation logic. If the validation fails, you can throw an exception, which prevents the object from being created. In other words, if the validation fails, the object will not be instantiated.
Example 2: Real-World Use Case
<?php
class Order {
public function __construct(
private string $orderId,
private float $amount
) {
if ($amount <= 0) {
throw new Exception("Order amount must be greater than 0");
}
if (!preg_match("/^ORD\d{4}$/", $orderId)) {
throw new Exception("Invalid Order ID Format");
}
}
public function showOrder() {
echo "Order ID: {$this->orderId} \n";
echo "Amount: {$this->amount}";
}
}
try {
$order = new Order("ORD1234", 4500.75);
$order->showOrder();
} catch (Exception $e) {
echo "Validation Failed: " . $e->getMessage();
}
echo "\n\n";
try {
$order2 = new Order("1234", -50); // Invalid
$order2->showOrder();
} catch (Exception $e) {
echo "Validation Failed: " . $e->getMessage();
}
?>
Output:
Order ID: ORD1234 Amount: 4500.75 Validation Failed: Order amount must be greater than 0
During the first object, which is valid:
- Order ID matches ORD1234
- Amount is greater than 0
- Object is created successfully
During the second object, which is invalid:
- Amount is -50 → Validation fails
- Throws exception → Prints error message
Benefits of Constructor Property Promotion
There are several advantages of using constructor property promotion:
1. Eliminates repetitive code:
- You don’t need to write separate class properties declarations and assignments. PHP automatically declares the property and assigns constructor argument values.
2. Improves readability:
- You can define declarations, visibility, and types of all properties in a single place — inside the constructor.
3. Easier maintenance:
- If you need to add, update, or remove a property, you only modify one location, not multiple places in the class.
4. Reduces human errors:
- Without constructor property promotion, you may forget to assign constructor parameters to class properties, leading to mismatches.
Constructor property promotion prevents this by promoting properties automatically.
Conclusion
Constructor Property Promotion in PHP 8 is a powerful feature that reduces code length and enhances readability. By promoting constructor parameters directly into class properties, PHP enables faster and more efficient object creation while keeping the syntax clean.
If you are building applications using frameworks like Laravel, Symfony, or Slim, this feature can significantly improve your code structure. We hope that you have understood the basic syntax of using constructor property promotion and practiced all the examples based on it.



