无法设置只读属性

发布于 2025-01-06 01:59:52 字数 179 浏览 1 评论 0原文

PHP 中是否确实存在只读属性而我不知道它们?如何使公共财产变为只读?

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

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

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';

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

§普罗旺斯的薰衣草 2025-01-13 01:59:52

从反射类的代码来看:

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

基本上,它明确禁止“name”和“class”属性。
但我找不到任何表明类属性存在的迹象!

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!

倚栏听风 2025-01-13 01:59:52

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

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!');
    }
}
?>
痴者 2025-01-13 01:59:52

PHP 文档

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

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

PHP docs:

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.

一笔一画续写前缘 2025-01-13 01:59:52

来自 ReflectionClass 的文档:

属性
姓名
班级名称。只读,尝试写入时抛出 ReflectionException。

然而,文档还说,

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

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

尽管该财产记录为普通公共财产,但事实上并非如此!

我懒得去深入研究 PHP 源代码,但你会发现那里有一个特殊的情况处理,它保护公共财产,使其只读。编辑:参见马克·贝克斯的回答。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文