无法设置只读属性

时间:2012-02-16 16:02:41

标签: php properties readonly

PHP中是否存在实际的只读属性,我不知道它们?如何将公共属性设置为只读?

我正在玩ReflectionClass,我在尝试覆盖属性时收到此错误消息:

$lol = new ReflectionObject($obj);
$lol->name = 'awawawawa';

4 个答案:

答案 0 :(得分:2)

从反射类的代码:

/* {{{ _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);     
    }
}
/* }}} */

所以基本上,它明确地禁止它为“名称”和“类”属性。 我找不到任何类属性存在的迹象!

答案 1 :(得分:1)

PHP docs

  

对象类的名称。只读,在尝试编写时抛出ReflectionException。

我在Properties页面中没有看到任何关于将内容设为只读的内容,但是......我猜可能会以final为前缀,但我不知道是否允许这样做它只在方法上提到过。

答案 2 :(得分:1)

来自ReflectionObject的PHP手册页:

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

他们是怎么做的没有太多,但我的猜测是它明确地寻找name属性的写入并阻止它发生,因为它会使反射变为谎言。

你可以自己做类似的事情:

<?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!');
    }
}
?>

答案 3 :(得分:1)

来自ReflectionClass的文档:

  

<强>属性
  名称
      班级名称。只读,在尝试编写时抛出ReflectionException。

然而,文档也说

ReflectionClass implements Reflector {
  /* Properties */
  public $ReflectionClass->name;
  ...

这里需要注意的是,(即使文档看起来ReflectionClass是用纯PHP实现的),ReflectionClass也是 PHP核心的一部分,因此在C中实现!

虽然该属性记录是一个普通的公共财产,但实际上并非如此!

我太懒了,不能深入研究PHP的源代码,但你会发现一个特殊的案例处理,它保护公共属性,使其成为只读。编辑:见Mark Ba​​kers回答。