Как реализовать переменную-член только для чтения в PHP? - PullRequest
9 голосов
/ 26 февраля 2010

При попытке изменить его выдается исключение.

Ответы [ 5 ]

20 голосов
/ 26 февраля 2010

Полагаю, решение для свойств класса было бы:

  • не определите свойство с именем, которое вас интересует
  • используйте магический метод __get для доступа к этому свойству, используя «поддельное» имя
  • определяет метод __set, поэтому он вызывает исключение при попытке установить это свойство.
  • См. Перегрузка , для получения дополнительной информации о магических методах.

Для переменных я не думаю, что возможно иметь переменную только для чтения, для которой PHP будет выдавать исключение, когда вы пытаетесь записать в нее.


Например, рассмотрим этот маленький класс:

class MyClass {
    protected $_data = array(
        'myVar' => 'test'
    );

    public function __get($name) {
        if (isset($this->_data[$name])) {
            return $this->_data[$name];
        } else {
            // non-existant property
            // => up to you to decide what to do
        }
    }

    public function __set($name, $value) {
        if ($name === 'myVar') {
            throw new Exception("not allowed : $name");
        } else {
            // => up to you to decide what to do
        }
    }
}

Создание экземпляра класса и попытка прочитать свойство:

$a = new MyClass();
echo $a->myVar . '<br />';

Получит ожидаемый результат:

test

При попытке написать в собственность:

$a->myVar = 10;

Вы получите исключение:

Exception: not allowed : myVar in /.../temp.php on line 19
14 голосов
/ 26 февраля 2010
class test {
   const CANT_CHANGE_ME = 1;
}

и вы называете его test::CANT_CHANGE_ME

2 голосов
/ 26 февраля 2010

Используйте константу. Ключевое слово const

0 голосов
/ 05 ноября 2018

Краткий ответ: вы не можете создать в PHP переменную-член, доступную только для чтения.

Фактически, большинство объектно-ориентированных языков считают плохой формой публичное раскрытие переменных-членов в любом случае ... (C # - большое, безобразное исключение с его конструкциями свойств).

Если вы хотите переменную класса, используйте ключевое слово const:

class MyClass {
    public const myVariable = 'x';
}

Доступ к этой переменной:

echo MyClass::myVariable;

Эта переменная будет существовать ровно в одной версии, независимо от того, сколько различных объектов типа MyClass вы создаете, и в большинстве объектно-ориентированных сценариев она практически не используется.

Если, однако, вам нужна переменная только для чтения, которая может иметь разные значения для каждого объекта, вы должны использовать закрытую переменную-член и метод доступа (a k a getter):

class MyClass {
    private $myVariable;
    public function getMyVariable() {
        return $this->myVariable;
    }
    public function __construct($myVar) {
        $this->myVariable = $myVar;
    }
}

Переменная устанавливается в конструкторе, и она становится доступной только для чтения, поскольку не имеет установщика. Но каждый экземпляр MyClass может иметь свое значение для myVariable.

$a = new MyClass(1);
$b = new MyClass(2);

echo $a->getMyVariable(); // 1
echo $b->getMyVariable(); // 2

$a->setMyVariable(3); // causes an error - the method doesn't exist
$a->myVariable = 3; // also error - the variable is private
0 голосов
/ 23 сентября 2016

Я знаю, что это старый вопрос, но ответ PASCAL действительно помог мне, и я хотел добавить к нему немного.

__ get () срабатывает не только на несуществующих свойствах, но и на «недоступных», например, защищенные. Это позволяет легко создавать свойства только для чтения!

class MyClass {
    protected $this;
    protected $that;
    protected $theOther;

    public function __get( $name ) {
        if ( isset( $this->$name ) ) {
            return $this->$name;
        } else {
            throw new Exception( "Call to nonexistent '$name' property of MyClass class" );
            return false;
        }
    }

    public function __set( $name ) {
        if ( isset( $this->$name ) ) {
            throw new Exception( "Tried to set nonexistent '$name' property of MyClass class" );
            return false;
        } else {
            throw new Exception( "Tried to set read-only '$name' property of MyClass class" );
            return false;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...