PHP RFC: Readonly Properties
- Version: 0.1.1
- Date: 2014-10-24 (Withdrawn 2014-11-03)
- Author: Andrea Faulds, ajf@ajf.me
- Status: Withdrawn
- Discussion: http://markmail.org/message/7l3ci3sboma2nlzq
- First Published at: http://wiki.php.net/rfc/readonly_properties
Introduction
There is currently no way to make a property readable to everyone and writeable only to the containing object, with PHP's visibility specifiers allowing all or nothing: a scope can either both read and write, or do neither. While _
_get
and _
_set
exist, these do not actually allow control of the same property, merely only exposing a separate property, and they are only usable for undeclared properties, which cannot be reflected and are not performant.
Because of this, getter and setter functions to control the ability to write to properties are common. This requires developers to write boilerplate code, even if assisted by IDEs, and is not as performant as a raw property.
Proposal
To deal with this, a new modifier keyword is introduced for properties, readonly
. It allows the property to be read from the normal scope of its visibility, so a public readonly
property is readable from the public scope, i.e. anywhere. However, it can only being written to from the next most restrictive scope, so a public readonly
property is writeable from the protected scope, and a protected readonly
property only from the private scope.
Due to implementation difficulties, this doesn't support for static properties for now. This may yet change, however. Properties cannot be both private
and readonly
, since there is no more restrictive scope than private
.
This keyword's behaviour should not be confused with that of C#'s readonly
specifier, which makes a property writeable only once, from a class's constructor. While the possible confusion this could produce is unfortunate, I could not think of a better name after much discussion. I don't think this precludes inclusion of a feature similar to that of C# under another name as there are other possible names for that feature, such as immutable
or final
. It's also worth noting that readonly
is already used for some classes (such as the DOM) in the PHP manual.
Example
Let's take this class:
class Stack { public readonly $size = 0; private $elements = []; public function push($elem) { $this->size++; $this->elements[] = $elem; } public function pop() { $this->size--; return array_pop($this->elements); } }
If we were to create an instance of this class and try to change size
we would get an error, as we cannot write to the public readonly
property from the public scope:
Fatal error: Cannot write to readonly public property Stack::$size in example.php on line 1
However, calling push
would not error, as it changes $size
from inside the class, which falls within the protected scope.
Backward Incompatible Changes
readonly
is now a reserved word, so it can't be used as a class, function, method or constant name.
It is possible that this could be changed so class, constant and function names are unaffected, but due to syntactical ambiguity, this couldn't be allowed for methods.
Proposed PHP Version(s)
This is proposed for the next major version of PHP, currently PHP 7.
Future Scope
Properties in interfaces are currently not supported. If they were later to be supported (perhaps with getters/setters being added), readonly
could be used to avoid compelling implementing classes from making a property writeable, but not preventing them from expanding the interface to do so, e.g.:
interface Point { readonly $x, $y; } class ImmutablePoint implements Point { public readonly $x, $y; ... } class MutablePoint implements Point { public $x, $y; ... }
RFC Impact
To Existing Extensions
Reflection has been updated, with the method ReflectionProperty::isReadonly()
being added.
To Opcache
The RFC's compatibility with opcache is yet to be verified. It merely adds a new ZEND_ACC_*
flag so support shouldn't be a problem, however.
Unaffected PHP Functionality
This does not affect methods or static properties.
Proposed Voting Choices
As this is a language change, a 2/3 majority is required.
Patches and Tests
A pull request against master is here: https://github.com/php/php-src/pull/879
It contains a full set of twelve different tests. There are no known issues at present.
A pull request for the language specification is here: https://github.com/php/php-langspec/pull/86
It currently lacks tests.
Implementation
After the project is implemented, this section should contain
- the version(s) it was merged to
- a link to the git commit(s)
- a link to the PHP manual entry for the feature
References
- An identical proposal was made eight years ago to internals as part of this discussion: http://marc.info/?l=php-internals&m=114739054505616&w=2
- This provides some of the functionality 2013's rejected Property Accessors Syntax RFC would have given with regards to being able to control the readability and writeability of a property separately, but without having the performance issues of getters and setters, not preventing use of references, and without creating an extra “real” property behind the scenes accessed via a virtual property, instead merely controlling the access to a normal property
Rejected Features
Keep this updated with features that were discussed on the mail lists.
Changelog
* v0.1.1 - Added Future Scope * v0.1 - Creatd