Re: [RFC] Primary Constructors
| From: | Rob Landers | Date: | Mon, 29 Jun 2026 20:22:46 +0000 |
| Subject: | Re: [RFC] Primary Constructors | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-131622@lists.php.net to get a copy of this message | ||
On Mon, Jun 29, 2026, at 18:59, Larry Garfield wrote:
[snip]
> The RFC has no mention of attributes. An example of that would be helpful, even though I
> presume it's exactly what one would expect it to be.
This was an oversight. I'll add the logic there. This is how they work:
1. Attributes on promoted primary-constructor params are reflected on both (just like promoted
properties):
1. ReflectionParameter
2. ReflectionProperty
2. Attributes on bare params remain parameter-only.
3. Target validation is context-sensitive, matching existing constructor promotion behavior:
1.
#[ParamAttr] public int $x appears on the property too, but newInstance() from
ReflectionProperty errors.
2. #[PropAttr] public int $x appears on the parameter too, but newInstance() from
ReflectionParameter errors.
4. Attributes before a class remain class attributes and are not copied to the synthesized
constructor.
The last one is debatable, but from what I can tell from grepping, putting attributes on
constructors is a very rare thing (39 out of 56,546 constructors). However, class-level attributes
are a more common thing. That being said, I'd be open to changing (4) to behave like
properties/parameters where it gets attached to the class and the constructor.
> The one addition I would ask for is to note that in Kotlin and Swift, there is a
> post-primary-constructor initializer, called an init block. It has
> no body, but lets you do post-property-assignment stuff. It's basically an argument-free
> constructor. I think that would go a long way toward smoothing the concerns people have about this
> feature being too "locked down."
>
> If we don't want a new keyword for it, we could allow a __construct method that has NO
> arguments if there is a primary constructor. It would get called last, after everything else
> (including parent constructors if appropriate) has run. (Whether it's spelled
> __construct() { ]] or __construct {
> }, I don't have a strong opinion.) A __construct that does take arguments
> would still be a compile-time conflict with a primary constructor.
>
> --Larry Garfield
>
I believe this should be a follow-up RFC. In PHP, the child decides when to call the parent
constructor — so "runs last, after parent constructors" requires defining a new
sequencing contract, which is a real design decision that deserves its own discussion rather than a
rider on this one. Beyond that, it also requires defining a syntax (you've sketched one
approach, Nick another -- both are interesting and that's exactly why it needs its own
discussion), rules (whether property lists should exist), and semantics. In essence, the description
would be a large (probably half) of the current RFC.
— Rob