Reputation: 11545
Are there actually read-only properties in PHP and I'm not aware of them? How do I get a public property to be read-only??
I was just playing with ReflectionClass and I got this error message when trying to overwrite a property:
$lol = new ReflectionObject($obj);
$lol->name = 'awawawawa';
Upvotes: 1
Views: 2346
Reputation: 20540
From the docs of ReflectionClass:
Properties
name
Name of the class. Read-only, throws ReflectionException in attempt to write.
However, the docs also say
ReflectionClass implements Reflector {
/* Properties */
public $ReflectionClass->name;
...
It is important to note here, that (even if the documentation looks ReflectionClass is implemented in pure PHP) the ReflectionClass is part of the PHP core, thus implemented in C!
Although the property is documented as being a normal public property, in fact its not!
I'm too lazy to dig into the PHP source code for this, but you will find a special case handling there which protects the public property making it read-only. EDIT: see Mark Bakers answer.
Upvotes: 1
Reputation: 212412
From the code of the reflection class:
/* {{{ _reflection_write_property */
static void _reflection_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
{
if ((Z_TYPE_P(member) == IS_STRING)
&& zend_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
&& ((Z_STRLEN_P(member) == sizeof("name") - 1 && !memcmp(Z_STRVAL_P(member), "name", sizeof("name")))
|| (Z_STRLEN_P(member) == sizeof("class") - 1 && !memcmp(Z_STRVAL_P(member), "class", sizeof("class")))))
{
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Cannot set read-only property %s::$%s", Z_OBJCE_P(object)->name, Z_STRVAL_P(member));
}
else
{
zend_std_obj_handlers->write_property(object, member, value TSRMLS_CC);
}
}
/* }}} */
so basically, it's explicitly forbidding it for the "name" and "class" properties. I can't find any indication that a class property exists though!
Upvotes: 3
Reputation: 1815
From the PHP Manual Page for ReflectionObject:
Properties
name
Name of the object's class. Read-only, throws ReflectionException in attempt to write.
http://sk.php.net/manual/en/class.reflectionobject.php
There isn't much on how they do this, but my guess would be that it's explicitly looking out for the writing of the name property and stopping it from happening as it would make the reflection a lie.
You could do something similar yourself:
<?php
class MyReadOnlyJunk
{
protected // over private, or not defined here at all
$name = 'My Name';
public function __set($key, $val)
{
if($key == 'name')
throw new Exception('Cannot has name set!');
}
}
?>
Upvotes: 1
Reputation: 324650
Name of the object's class. Read-only, throws ReflectionException in attempt to write.
I don't see anything in the Properties
page about making things read-only, though... I guess possibly prefix them with final
, but I don't know if that's allowed since it's only mentioned on methods.
Upvotes: 1