Readonly property default values (PHP 8.6)
From PHP 8.1, when readonly properties were introduced, through PHP 8.5, a readonly property cannot declare an explicit default value; the compiler rejects it. The Readonly Property Defaults RFC removes that restriction for instance readonly properties, including the implicitly readonly properties of a readonly class. No new syntax is added. Default values follow the same rules as for other properties.
Status and versions
| Event | Evidence |
|---|---|
| RFC version 1.0, dated 2026-07-04 | RFC page |
| Vote passed 24 yes, 0 no, 5 abstain (2/3 majority needed); the poll is closed | RFC page |
Merged to php-src on 2026-08-11 (commit a2640ae, PR #22588) |
php-src commit |
Listed under PHP 8.6 New Features → Core in UPGRADING on the PHP-8.6 branch |
php-src UPGRADING, read 2026-10-12 |
A GitHub comparison shows the commit is already in the php-8.6.0RC1 tag. As of 12 October
2026, PHP 8.6 has reached release candidates but is not generally available, so no stable
PHP release has this behavior yet. The RFC lists no backward-incompatible changes.
Behavior described by the RFC
- The default value counts as the initializing assignment, so the property is already set when the object is created, before the constructor runs. Any later assignment, including one in the constructor, fails with a "Cannot modify readonly property" error.
unset()of such a property throws, because it is already initialized. So the lazy pattern of unsetting it and then initializing it in__get()only works for readonly properties without a default.- When cloning, the property can still be reinitialized once in
__clone(), or with clone-with, like any other initialized readonly property. - The property is included in serialized data, and unserialization may restore a different
value, both through native hydration and through
__unserialize(). - Inheritance and trait rules are unchanged. Two traits that declare the same readonly property can be combined only if their default values are the same.
- Reflection reports
isReadOnly()andhasDefaultValue()astrue, andgetDefaultValue()returns the declared value. - With asymmetric visibility, a later write fails as a readonly modification whatever the
setvisibility is.
The RFC's main argument is interface properties (PHP 8.4). A readonly property with a
default satisfies a get-only ({ get; }) interface property but not one that also requires
set. This lets a class provide fixed values for such an interface without assigning them
in the constructor.
Limitations
- Not changed: static properties, property hooks (readonly properties still cannot have hooks), and promoted constructor parameters, where a default is still only a parameter default.
- The RFC notes that IDEs and static analysers that flag these defaults as errors need updating. Whether a given tool supports the feature yet was not checked here.
- The RFC page's code examples were not reproduced, and the behavior above was not tested against a PHP 8.6 build.