php PHP只读属性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/402215/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP Readonly Properties?
提问by mazniak
In using PHP's DOM classes (DOMNode, DOMEElement, etc) I have noticed that they possess truly readonly properties. For example, I can read the $nodeName property of a DOMNode, but I cannot write to it (if I do PHP throws a fatal error).
在使用 PHP 的 DOM 类(DOMNode、DOMEElement 等)时,我注意到它们拥有真正的只读属性。例如,我可以读取 DOMNode 的 $nodeName 属性,但我无法写入它(如果我这样做,PHP 会引发致命错误)。
How can I create readonly properties of my own in PHP?
如何在 PHP 中创建自己的只读属性?
采纳答案by too much php
You can do it like this:
你可以这样做:
class Example {
private $__readOnly = 'hello world';
function __get($name) {
if($name === 'readOnly')
return $this->__readOnly;
user_error("Invalid property: " . __CLASS__ . "->$name");
}
function __set($name, $value) {
user_error("Can't set property: " . __CLASS__ . "->$name");
}
}
Only use this when you really need it - it is slower than normal property access. For PHP, it's best to adopt a policy of only using setter methods to change a property from the outside.
仅在您真正需要时才使用它 - 它比正常的属性访问慢。对于 PHP,最好采用只使用 setter 方法从外部更改属性的策略。
回答by Matt
But private properties exposed only using __get() aren't visible to functions that enumerate an object's members - json_encode() for example.
但是仅使用 __get() 公开的私有属性对于枚举对象成员的函数是不可见的 - 例如 json_encode()。
I regularly pass PHP objects to Javascript using json_encode() as it seems to be a good way to pass complex structures with lots of data populated from a database. I have to use public properties in these objects so that this data is populated through to the Javascript that uses it, but this means that those properties have to be public (and therefore run the risk that another programmer not on the same wavelength (or probably myself after a bad night) might modify them directly). If I make them private and use __get() and __set(), then json_encode() doesn't see them.
我经常使用 json_encode() 将 PHP 对象传递给 Javascript,因为它似乎是传递具有从数据库填充的大量数据的复杂结构的好方法。我必须在这些对象中使用公共属性,以便将此数据填充到使用它的 Javascript,但这意味着这些属性必须是公共的(因此冒着另一个程序员不在同一波长上(或可能在一个糟糕的夜晚之后我自己)可能会直接修改它们)。如果我将它们设为私有并使用 __get() 和 __set(),那么 json_encode() 就看不到它们。
Wouldn't it be nice to have a "readonly" accessibility keyword?
有一个“只读”可访问性关键字不是很好吗?
回答by Matt
I see you have already got your answer but for the ones who still are looking:
我看到您已经得到了答案,但对于仍在寻找的人:
Just declare all "readonly" variables as private or protected and use the magic method __get() like this:
只需将所有“只读”变量声明为私有或受保护的,并像这样使用魔术方法 __get() :
/**
* This is used to fetch readonly variables, you can not read the registry
* instance reference through here.
*
* @param string $var
* @return bool|string|array
*/
public function __get($var)
{
return ($var != "instance" && isset($this->$var)) ? $this->$var : false;
}
As you can see I have also protected the $this->instance variable as this method will allow users to read all declared variabled. To block several variables use an array with in_array().
如您所见,我还保护了 $this->instance 变量,因为此方法将允许用户读取所有声明的变量。要阻止多个变量,请使用带有 in_array() 的数组。
回答by Le Petit Monde de Purexo
Here is a way to render all property of your class read_only from outside, inherited class have write access ;-).
这是一种从外部呈现类的所有属性 read_only 的方法,继承的类具有写访问权限;-)。
class Test {
protected $foo;
protected $bar;
public function __construct($foo, $bar) {
$this->foo = $foo;
$this->bar = $bar;
}
/**
* All property accessible from outside but readonly
* if property does not exist return null
*
* @param string $name
*
* @return mixed|null
*/
public function __get ($name) {
return $this->$name ?? null;
}
/**
* __set trap, property not writeable
*
* @param string $name
* @param mixed $value
*
* @return mixed
*/
function __set ($name, $value) {
return $value;
}
}
tested in php7
在 php7 中测试
回答by Precastic
For those looking for a way of exposing your private/protected properties for serialization, if you choose to use a getter method to make them readonly, here is a way of doing this (@Matt: for json as an example):
对于那些正在寻找一种公开您的私有/受保护属性以进行序列化的方法的人,如果您选择使用 getter 方法将它们设置为只读,这是一种方法(@Matt:以 json 为例):
interface json_serialize {
public function json_encode( $asJson = true );
public function json_decode( $value );
}
class test implements json_serialize {
public $obj = null;
protected $num = 123;
protected $string = 'string';
protected $vars = array( 'array', 'array' );
// getter
public function __get( $name ) {
return( $this->$name );
}
// json_decode
public function json_encode( $asJson = true ) {
$result = array();
foreach( $this as $key => $value )
if( is_object( $value ) ) {
if( $value instanceof json_serialize )
$result[$key] = $value->json_encode( false );
else
trigger_error( 'Object not encoded: ' . get_class( $this ).'::'.$key, E_USER_WARNING );
} else
$result[$key] = $value;
return( $asJson ? json_encode( $result ) : $result );
}
// json_encode
public function json_decode( $value ) {
$json = json_decode( $value, true );
foreach( $json as $key => $value ) {
// recursively loop through each variable reset them
}
}
}
$test = new test();
$test->obj = new test();
echo $test->string;
echo $test->json_encode();
回答by Precastic
Class PropertyExample {
private $m_value;
public function Value() {
$args = func_get_args();
return $this->getSet($this->m_value, $args);
}
protected function _getSet(&$property, $args){
switch (sizeOf($args)){
case 0:
return $property;
case 1:
$property = $args[0];
break;
default:
$backtrace = debug_backtrace();
throw new Exception($backtrace[2]['function'] . ' accepts either 0 or 1 parameters');
}
}
}
This is how I deal with getting/setting my properties, if you want to make Value() readonly ... then you simply just have it do the following instead:
这就是我如何处理获取/设置我的属性,如果你想让 Value() 只读......那么你只需让它执行以下操作:
return $this->m_value;
Where as the function Value() right now would either get or set.
现在函数 Value() 要么获取要么设置。

