Constructor Property Promotion

Before PHP 8.0, giving a class a typed property meant declaring the property, then repeating its name and type in the constructor just to copy the argument across. Here is the long-hand version.

<?php
class Point {
  public float $x;
  public float $y;

  public function __construct(float $x, float $y) {
    $this->x = $x;
    $this->y = $y;
  }
}

$p = new Point(1.5, 2.5);
echo "{$p->x}, {$p->y}\n";
?>

1.5, 2.5
Constructor property promotion lets a constructor parameter declare the property too, by giving the parameter a visibility modifier (public, protected or private). PHP then declares the property and assigns it automatically — no property declaration and no $this->x = $x needed.

<?php
class Point {
  public function __construct(
    public float $x,
    public float $y
  ) {
  }
}

$p = new Point(1.5, 2.5);
echo "{$p->x}, {$p->y}\n";
?>

1.5, 2.5
A constructor can mix promoted parameters with ordinary ones. An ordinary (non-promoted) parameter is not turned into a property automatically — it behaves just like any other constructor argument, and the class can still declare its own plain properties alongside the promoted ones.

<?php
class User {
  public string $slug; // an ordinary, non-promoted property

  public function __construct(
    public string $name,     // promoted
    private int $age,        // promoted
    string $prefix = 'user'  // ordinary parameter, not a property
  ) {
    $this->slug = strtolower($prefix . '-' . str_replace(' ', '-', $name));
  }

  public function getAge(): int {
    return $this->age;
  }
}

$u = new User('Jane Doe', 30);
echo $u->name, "\n";
echo $u->slug, "\n";
echo $u->getAge(), "\n";
?>

Jane Doe user-jane-doe 30
Promoted properties can also be typed, given default values, and (since PHP 8.5) marked final, exactly like ordinary property declarations. A final promoted property can still be read by a child class, but the child may not redeclare or override it.

<?php
class Base {
  public function __construct(final public string $id) {
  }
}

class Child extends Base {
  // no attempt to redeclare $id here
}

$c = new Child('abc-1');
echo $c->id, "\n";
?>

abc-1
Promoted properties are often combined with readonly (see Readonly Properties and Classes), eg. public readonly float $x, to make the object immutable after construction.