====== 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 [[rfc:propertygetsetsyntax-v1.2|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