Como implementar uma variável de membro somente leitura em PHP?
-
23-09-2019 - |
Pergunta
Ao tentar alterá-lo, lance uma exceção.
Solução
Suponho que uma solução, para propriedades de classe, seria::
- não definir uma propriedade com o nome que lhe interessa
- Use a magia
__get
Método para acessar essa propriedade, usando o nome "falso" - Defina a
__set
Método, portanto, ele lança uma exceção ao tentar definir essa propriedade. - Ver Sobrecarga, para mais informações sobre métodos mágicos.
Para variáveis, não acho que seja possível ter uma variável somente leitura para a qual o PHP lançará uma exceção quando você estiver tentando escrever para ela.
Por exemplo, considere esta pequena classe:
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
}
}
}
Instanciando a aula e tentando ler a propriedade:
$a = new MyClass();
echo $a->myVar . '<br />';
Vai obter a saída esperada:
test
Enquanto tenta escrever para a propriedade:
$a->myVar = 10;
Terá uma exceção:
Exception: not allowed : myVar in /.../temp.php on line 19
Outras dicas
class test {
const CANT_CHANGE_ME = 1;
}
e você o refere como test::CANT_CHANGE_ME
Use uma constante. Palavra -chave const
Eu sei que esta é uma pergunta antiga, mas a resposta do PASCAL realmente me ajudou e eu queria acrescentar um pouco.
__get() dispara não apenas em propriedades inexistentes, mas também em propriedades "inacessíveis", por exemplo.os protegidos.Isso facilita a criação de propriedades somente leitura!
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;
}
}
}
A resposta curta é que você não pode criar uma variável de membro de objeto somente leitura em PHP.
Na verdade, a maioria das linguagens orientadas a objetos considera uma forma inadequada expor publicamente as variáveis-membro de qualquer maneira...(C# sendo a grande e feia exceção com suas construções de propriedades).
Se você quiser uma variável de classe, use o const
palavra-chave:
class MyClass {
public const myVariable = 'x';
}
Esta variável pode ser acessada:
echo MyClass::myVariable;
Esta variável existirá em exatamente uma versão, independentemente de quantos objetos diferentes do tipo MyClass
você cria e, na maioria dos cenários orientados a objetos, tem pouca ou nenhuma utilidade.
Se, no entanto, você deseja uma variável somente leitura que possa ter valores diferentes por objeto, você deve usar uma variável de membro privada e um método acessador (também conhecido como getter):
class MyClass {
private $myVariable;
public function getMyVariable() {
return $this->myVariable;
}
public function __construct($myVar) {
$this->myVariable = $myVar;
}
}
A variável é definida no construtor e se torna somente leitura por não ter um setter.Mas cada instância de MyClass
pode ter seu próprio valor para 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