Edit report at https://bugs.php.net/bug.php?id=46506&edit=1
ID: 46506
Comment by: stian dot pedersen at gmail dot com
Reported by: glideraerobatics at hotmail dot com
Summary: readonly attribute for (public) class variables
Status: Open
Type: Feature/Change Request
Package: *General Issues
PHP Version: 5.4
Block user comment: N
Private report: N
New Comment:
This feature is seconded. Basically it would be useful to have a modifier which
allows internal modification but disallows public reassignment. By an example,
letting "property" be the new key word,
class Order
{
property $customer;
}
class Order
{
private $customer;
public getCustomer(){return $this->customer;}
}
$order->customer and $order->getCustomer() could have the same semantics in
that
a "copy of the pointer" in C terms is returned and you cannot call $order-
>customer = null any more than you could call $order->getCustomer() = null.
However, $customer itself should be modifyable, for instance, $order->customer-
>id = 1000, if id is declared as public. This would be more in tune of mat dot
barrie at gmail dot com and very useful in OOP.
Inside the class, I would prefer to be able to reassign customer at will (even
after constructor).
Syntactically it would be nice to chose a syntax that would allow support for
setters also, but for now, I would be happy with this. It sorta does the same
thing as the __get() trick but does not mess up IDE support and will probably
execute faster.
Previous Comments:
------------------------------------------------------------------------
[2012-11-27 15:55:04] info at strictcoding dot co dot uk
+1 for this awesome feature. Any reviews from the PHP team?
------------------------------------------------------------------------
[2012-09-18 21:53:20] mat dot barrie at gmail dot com
As a point of interest, the C# readonly keyword mentioned actually does not
protect exposed classes from being modified, it prevents assignment. So from
your example if you duplicate the C# behaviour, this is what it actually would
work like this, which I don't think is what you're asking for:
--
$count = count($parent->children); // You can do this
$name = $parent->children[0]; // You can even do this
$parent->children[0] = "BILLY"; // You can still do this
$parent->children[] = "BOB"; // And you can still even do this
$parent->children = NULL; // But not this
unset($parent->children); // Or this
--
A readonly attribute probably isn't what's needed here (after all, you're not
actually asking for a property that can be made readonly) but instead if the
protection level could be defined on the getter and setter independently, so
that set could be defined as private and get as public. __get and __set sort
of
do this, but they're useless if you're serialising, hurt performance, and
unless
I'm missing something you can't add phpDoc comments to the exposed pseudo-
properties.
------------------------------------------------------------------------
[2012-01-25 08:11:40] glideraerobatics at hotmail dot com
Changed affected PHP version.
------------------------------------------------------------------------
[2012-01-24 23:12:32] luke at cywh dot com
I just want the "readonly" keyword to protect a property from being written to
from the outside. I still want to write to the property from within the class.
Here's a simple example of how it could be used:
class Parent
{
readonly public $children = array();
public function addChild($childName)
{
$this->children[] = ucwords(strtolower($childName));
}
}
$parent = new Parent;
$parent->addChild("billy");
$count = count($parent->children); // You can do this
print "Parent has $count children\n";
$name = $parent->children[0]; // You can even do this
print "Parent's first child's name is $name\n";
$parent->children[0] = "BILLY"; // But you can't do this
$parent->children[] = "BOB"; // Or this
$parent->children = NULL; // Or this
unset($parent->children); // Or this
The above example frees you from having to do this:
class Parent
{
protected $children = array();
public function addChild($childName)
{
$this->children[] = ucwords(strtolower($childName));
}
public function hasChild($index)
{
return isset($this->children[$index]);
}
public function getChild($index)
{
return $this->children[$index];
}
public function childCount()
{
return count($this->children);
}
}
I've had to write MANY classes like this. The has/isset, get, and count
functions are virtually all the same.
Some people have even resorted to using __get and __set:
http://stackoverflow.com/questions/402215/php-readonly-properties
The __get and __set magic functions are slow, so much so you're better off
making your own getters and setters, which is multiplied by the number of
properties you need like this in the class.
I would recommend the following definitions:
readonly public = read for public, write for protected
readonly protected = read for protected, write for private
I think this should satisfy most cases.
------------------------------------------------------------------------
[2009-07-12 13:27:08] mickael at lupusmic dot org
I guess the readonly keyword in C# is wrong. It hasn't to disallow variance of
the attribute, but the setting from outside the object. Readonly is opposite to
constness of a variable. For example, DOMDocument::doctype isn't constant.
What you think about, it's a dynamic const attribute, in opposite to static one.
So said, a readonly is like a const attribute, but isn't. And it doesn't
deserve a scope qualifier, it can only be public.
For example :
class thing
{
readonly $status = 'instantiation' ;
public function __construct()
{
// do init stuff
$this->status = 'instantiate' ;
}
public function invalidate()
{
// do stuf
$this->status = 'invalid' ;
}
}
// Usage
$o = new thing ;
echo $o->status ; // display 'instantiation'
$o->status = 'forced' ; // throw an error E_FATAL
$o->invalidate() ; // do stuff then set readonly status attribute
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=46506
--
Edit this bug report at https://bugs.php.net/bug.php?id=46506&edit=1