rfc:readonly_classes

PHP RFC: Readonly classes

Introduction

PHP 8.1 added support for readonly properties via PHP RFC: Readonly properties 2.0. However, it's still not easy to declare (quasi-)immutable classes, especially if they contain many properties. Therefore, this RFC proposes to add support for readonly classes.

Proposal

The usage of the readonly modifier added by PHP RFC: Readonly properties 2.0 is extended to classes:

readonly class Test {
    public string $prop;
}

Doing so will implicitly mark all instance properties of a class as readonly. Furthermore, it will prevent the creation of dynamic properties.

readonly class Foo
{
    public int $bar;
 
    public function __construct() {
        $this->bar = 1;
    }
}
 
$foo = new Foo();
$foo->bar = 2;
// Fatal Error: Uncaught Error: Cannot modify readonly property Foo::$bar
 
$foo->baz = 1;
// Fatal Error: Uncaught Error: Cannot create dynamic property Foo::$baz

PHP RFC: Deprecate dynamic properties added support for the #[AllowDynamicProperties] attribute which makes it possible to create dynamic properties without triggering errors. In order not to violate the read-only constraint, marking readonly classes with the above attribute is a compile-time error:

#[AllowDynamicProperties]
readonly class Foo {
}
 
// Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class Foo

Restrictions

As neither untyped, nor static properties are covered by the Readonly properties RFC, readonly classes cannot declare them either:

readonly class Foo
{
    public $bar;
}
 
// Fatal error: Readonly property Foo::$bar must have type
readonly class Foo
{
    public static int $bar;
}
 
// Fatal error: Readonly class Foo cannot declare static properties

Inheritance

Similarly how overriding of readonly properties works, a readonly class can only extend a readonly parent:

readonly class A {}
readonly class B extends A {} // valid

But both of the following are illegal:

readonly class A {}
class B extends A {}
// Fatal error: Non-readonly class B cannot extend readonly class A
class A {}
readonly class B extends A {}
// Fatal error: Readonly class B cannot extend non-readonly class A

Reflection

A ReflectionClass::isReadOnly() method is added, which reports whether a class is declared as read-only. Additionally, ReflectionClass::getModifiers() will also include the ReflectionClass::IS_READONLY flag.

Backward Incompatible Changes

None.

Errata

  • https://github.com/php/php-src/issues/9285: It used to be possible to add non-readonly properties to readonly classes via traits. As on PHP 8.2 RC 1, traits cannot be used by readonly classes if they define any non-readonly property, otherwise a compilation error is emitted.

Vote

Voted started on 2022-04-27, ending on 2022-05-11

Add readonly classes as proposed?
Real name Yes No
asgrim (asgrim)  
ashnazg (ashnazg)  
beberlei (beberlei)  
bukka (bukka)  
bwoebi (bwoebi)  
crell (crell)  
cschneid (cschneid)  
derick (derick)  
didou (didou)  
diegopires (diegopires)  
dmitry (dmitry)  
dragoonis (dragoonis)  
galvao (galvao)  
geekcom (geekcom)  
girgias (girgias)  
jbnahan (jbnahan)  
jhdxr (jhdxr)  
kocsismate (kocsismate)  
lcobucci (lcobucci)  
lstrojny (lstrojny)  
lufei (lufei)  
mauricio (mauricio)  
mgocobachi (mgocobachi)  
nicolasgrekas (nicolasgrekas)  
ocramius (ocramius)  
pierrick (pierrick)  
pollita (pollita)  
reywob (reywob)  
santiagolizardo (santiagolizardo)  
sebastian (sebastian)  
sergey (sergey)  
stas (stas)  
theodorejb (theodorejb)  
weierophinney (weierophinney)  
wyrihaximus (wyrihaximus)  
Final result: 28 7
This poll has been closed.
rfc/readonly_classes.txt · Last modified: 2022/08/21 08:47 by kocsismate