[PHP-DEV] Multiple property assigning without constructor

Hi Internals,

I would like to discuss the possibility of assigning multiple public properties at once during the class initialization.
Currently, with constructor property promotion we’ve already achieved the ability to skip a lot of boilerplate code. With property accessors (aka hooks) we could rid of getters and setters. But often classes need constructors only to set properties. In such cases, constructors become redundant.

Here are a few examples:

class Person
{
public string $firstName;
public int $age;
}

$person = new Person {
firstName: "John",
age: 42
};

The initialization becomes “struct-like” but it should not affect the current state and in general it makes code work like this:

$person = new Person();
$person->firstName = "John";
$person->age = 42;

In case if constructor exists, multiple property assignment just rewrites values, so it could even be something like following:


class Person
{
public function __construct(
public string $firstName,
public int $age
) {
}

$person = new Person("Name", 43) {
firstName: "John",
age: 42
};

}

However, the syntax is the question and it could be done similarly to: https://wiki.php.net/rfc/compact-object-property-assignment

Also, such “functionality” could be reused for cloning and maybe for other appropriate cases:


$person = new Person {
firstName: "John",
age: 42
};

$person2 = clone $person {
firstName: "John Doe",
age: 43
}

Taras Chornyi

$person = new Person(“Name”, 43) {

firstName: “John”,

age: 42

};

Hi!

You could achieve similar functionality with a simple user-land method “assign”. If you put such a method on a trait, you can use it everywhere.

See the example:

<?php trait AssignsPropertiesValues { public function assign(...$props): static { foreach ($props as $propName => $propVal) { $this->$propName = $propVal; } return $this; } } class Person { use AssignsPropertiesValues; public function __construct( public string $firstName, public int $age ) { } } class Person2 { use AssignsPropertiesValues; public string $firstName; public int $age; } class Person3 { use AssignsPropertiesValues; public string $firstName { set => \strtoupper($value); } public int $age; } $p1 = new Person('Pig',5)->assign(firstName: 'Peppa', age: 6); $p2 = new Person2()->assign(firstName: 'George', age: 3); $p3 = new Person3()->assign(firstName: 'Danny', age: 7); var_dump($p1, $p2, $p3); [https://3v4l.org/F83NO#v8.4.1](https://3v4l.org/F83NO#v8.4.1) Best regards, Erick

But often classes need constructors only to set properties. In such cases, constructors become redundant.

Actually, the behavior is not the same and the constructors are not redundant.

Taking your example:

class Person
{
    public string $firstName;
    public int $age;
}

$person = new Person {
   firstName: "John",
   age: 42
};

This would allow the following:

$invalidPerson = new Person();

Now we have a person without name or age. But with constructors we
make sure that the object is always in a valid state:

class Person
{
    public function __construct(public string $firstName, public int $age)
    { }
}

$validPerson = new Person('Name', 40);
$invalidPerson = new Person(); // this is impossible. every person
needs firstName and age

I just wanted to point that out. :slight_smile: