Невозможно установить свойство только для чтения - PullRequest
1 голос
/ 16 февраля 2012

Есть ли в PHP свойства, доступные только для чтения, и я о них не знаю?Как мне сделать общедоступное свойство доступным только для чтения ??

Я просто играл с ReflectionClass и получил сообщение об ошибке при попытке перезаписать свойство:

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

Ответы [ 4 ]

2 голосов
/ 16 февраля 2012

Из кода класса отражения:

/* {{{ _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". Я не могу найти никаких признаков того, что свойство класса существует!

1 голос
/ 16 февраля 2012

со страницы руководства PHP для 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

Не так уж много на как они это делают, но я думаю, что он явно следит за записью свойства 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!');
    }
}
?>
1 голос
/ 16 февраля 2012

Из документов ReflectionClass :

Свойства
имя
Наименование класса. Только для чтения, генерирует ReflectionException при попытке записи.

Однако в документах также написано

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

Здесь важно отметить, что (даже если документация выглядит как ReflectionClass реализован на чистом PHP), ReflectionClass является частью ядра PHP , таким образом реализованного в C!

Хотя свойство задокументировано как обычная публичная собственность, на самом деле это не так!

Мне лень копаться в исходном коде PHP для этого, но вы найдете там специальную обработку, которая защищает открытое свойство, делая его доступным только для чтения. РЕДАКТИРОВАТЬ: см. Ответ Марк Бейкерс.

1 голос
/ 16 февраля 2012

PHP документы :

Имя класса объекта. Только для чтения, генерирует ReflectionException при попытке записи.

Я не вижу на странице Properties ничего о том, чтобы сделать вещи доступными только для чтения, хотя ... Я думаю, возможно, добавьте к ним префикс final, но я не знаю, разрешено ли это, поскольку это упоминается только в методы.

...