Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

gadreel's avatar

Constructor property promotion

Hi all. I would like a small clarification regarding constructor property promotion.

When you have a parent class and child class with constructor property promotion. What it the correct way to write the parent properties on the child class?

I think if I type protected User $user on the child class it will create the property on the Child Class overriding the parent property which is unnecessary.

// Parent
abstract class ParentClass
{
    /**
     * Create a new event instance.
     *
     * @param  User  $user
     */
    public function __construct(protected User $user)
    {
        //
    }
}
//Child
class ChildClass extends ParentClass
{
    /**
     * Create a new event instance.
     *
     * @param  User  $user
     * @param  AnotherClass $object
     */
    public function __construct(protected User $user, public AnotherClass $object)
    {
        parent::__construct($user);
    }
}

OR

//Child
class ChildClass extends ParentClass
{
    /**
     * Create a new event instance.
     *
     * @param  User  $user
     * @param  AnotherClass $object
     */
    public function __construct(User $user, public AnotherClass $object)
    {
        parent::__construct($user);
    }
}
0 likes
7 replies
Glukinho's avatar

I don't get what you're asking. Child class constructor overrides parent's, so you should duplicate parent's fields to make child have them too (don't forget to call parent::__construct(...). Or you may omit parent's fields and child class will not have them.

What is the real difference between two options you gave?

https://stitcher.io/blog/constructor-promotion-in-php-8

Inheritance Since PHP constructors don't need to follow the declaration of their parent constructor, there's little to be said: inheritance is allowed. If you need to pass properties from the child constructor to the parent constructor though, you'll need to manually pass them

Upd: by the way, you must prepend promoted property with public/protected/private keyword, so this is not allowed:

// You must declare visibility of $user

public function __construct(User $user, public AnotherClass $object)
martinbean's avatar

@gadreel This is one of the reasons I don’t like property promotion, to be honest.

If I’m assigning a value to a property, I’d still rather much see that explicitly happening. I should be able to scan-read a class, see the properties it declares, and then see where those properties’ values are being assigning. Not this weird do-both-at-once syntax in a constructor that then also leaves constructor methods with empty bodies—it just looks gross.

Glukinho's avatar

@martinbean on the other hand, typing variable name "user" 4 times (6 times including property class name) just to add it to a class was killing me :(

class Project
{
    private User $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }
}

Now you type visibility/class name/property name only once which is such a relief to me.

martinbean's avatar

@Glukinho But I can follow that code in a logical manner:

  • The class has a private property of type User and name $user
  • The class constructor requires an argument of type User
  • The argument in the class constructor is then assigned to the class property.

Whereas this:

public function __construct(private User $user)
{
}

On first glance it just looks like a method with a parameter and no body. You have to actually read it to go, “Oh, no, the argument has a visibility modifier so it’s actually implicitly assigning a property as well.”

It’s even worse if you have a mixture of some declared properties but not all:

class Foo
{
    protected Bar $assignedValueByMethodOtherThanConstructor;

    public function __construct(protected Foo $foo)
    {
    }
}

This class actually has two properties, but you don’t know for glancing because of the different paradigms in use in this one class for assigning values. Whereas before, when all properties were declared…

class Foo
{
    protected Foo $foo;
    protected Bar $assignedValueByMethodOtherThanConstructor;
}

…you could see what properties a class had in a single glance. But I seem to be very much in the minority on this, as everyone seems to have taken to property promotion as the new shiny-shiny.

1 like
Glukinho's avatar

@martinbean Totally agree. But old style always was annoying me. I'm glad to write less code and see less code too. Also it was pain when I had to move some properties to another class, or edit property names etc.

Tray2's avatar

@martinbean I totally agree, it's much easier to see all the properties defined in the class and then assigned in the constructor or by other methods, than defining them in the constructors arguments.

The thing that annoys me most is the empty { }.

1 like

Please or to participate in this conversation.