Skip to content
Theory · Classes and objects · lesson 2 of 11

The constructor and promotion

In the previous lesson every new object got its starting values from the class: the counter always started at 0. But much cannot be known in advance. Every user has their own name, and it has to be set at the moment the object appears.

Let's go back to the houses. The builders don't start empty-handed: they get the order right away—how many floors and what color the walls are. From that order the house is built the way it should be from the start.

The __construct method

In PHP the constructor takes that order. A constructor is a method named __construct that PHP calls by itself when new builds an object. The arguments of new User('Anna') go into its parameters:

PHP
<?php

class User
{
    public string $name;

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

$anna = new User('Anna');
echo $anna->name, "\n"; // Anna

Let's go through it step by step:

  1. public string $name; declares a property with no starting value: the name will come from outside.
  2. new User('Anna') builds an object and at once calls its __construct with the string 'Anna'.
  3. Inside the constructor $this is the new object, and $this->name = $name; writes the name into its property.
  4. The finished object goes into $anna, and echo prints Anna.

Two underscores at the start of a name mark the methods PHP calls by itself. You don't write $anna->__construct('Anna'): the constructor runs once, on every new.

Property promotion

Look at how many times the name appears in the class User: in the property declaration, in the parameter and in the assignment. Every new property would take three lines. Since PHP 8.0 one notation does all of it:

PHP
<?php

class User
{
    public function __construct(
        public string $name,
        public int $level = 1,
    ) {}
}

$anna = new User('Anna');
$boris = new User('Boris', 3);
echo $anna->name, ' ', $anna->level, "\n"; // Anna 1
echo $boris->name, ' ', $boris->level, "\n"; // Boris 3

Property promotion is the notation in which the word public before a constructor parameter declares a property and assigns the argument to it. Let's take it apart:

  1. public string $name creates the property $name and puts the first argument of new into it.
  2. public int $level = 1 works the same way, but the parameter has a default value: new User('Anna') gets level 1.
  3. The constructor body is empty, {}: promotion did all the work. If there is a body, it runs after the properties are written.
  4. Each object has its own values, so the program prints Anna 1 and Boris 3.

Instead of public you can write private or protected: then the property is closed to code outside the class. These three words are called visibility modifiers. The type can also be a class name: the parameter private Logger $log declares a property that holds an object of the class Logger.

Interviewers ask what property promotion does. The answer:

  • a modifier on a constructor parameter declares the property and assigns the argument to it in one step;
  • the line $this->name = $name; is no longer needed;
  • the result is an ordinary property, separate in each object, with a type and a default value if you give them.

Common mistake

A property was declared without a starting value and never set in the constructor:

PHP
<?php

class Order
{
    public int $total;
}

$order = new Order();
echo $order->total, "\n"; // ✗
TEXT
Fatal error: Uncaught Error: Typed property Order::$total must not be accessed before initialization

This is an error, not a warning: the program stops at that line. A typed property that was given no value is in a special "not set" state, and that is not null. Here the house picture breaks down: you can at least look around an unfinished house, but PHP won't let you read a property that was never set.

The fix is to give the property a starting value, public int $total = 0;, or to write it in the constructor.

Key points

  • The constructor __construct runs by itself on every new and gets the arguments of new User('Anna').
  • Property promotion: public string $name among the constructor parameters declares a property and assigns the argument to it.
  • A promoted parameter may have a default value: public int $level = 1.
  • A typed property with no value cannot be read: that is an Error, not null.