我正在编写一个使用__get()
和__set()
来存储和检索主数组中的数组元素的类。我检查了一些元素是不可能的,基本上是为了重新创建私有属性。
我注意到__get
似乎拦截了对类属性的所有调用。这对我来说很糟糕,因为我想让外部世界变量私有(通过get不可用),但我试图通过直接引用类中的主数组来访问它。当然,主数组不在gettable属性的白名单中:(
有没有办法可以在使用__get()
和__set()
的php类中模拟公共和私有属性?
示例:
<?
abstract class abstraction {
private $arrSettables;
private $arrGettables;
private $arrPropertyValues;
private $arrProperties;
private $blnExists = FALSE;
public function __construct( $arrPropertyValues, $arrSettables, $arrGettables ) {
$this->arrProperties = array_keys($arrPropertyValues);
$this->arrPropertyValues = $arrPropertyValues;
$this->arrSettables = $arrSettables;
$this->arrGettables = $arrGettables;
}
public function __get( $var ) {
echo "__get()ing:\n";
if ( ! in_array($var, $this->arrGettables) ) {
throw new Exception("$var is not accessible.");
}
return $this->arrPropertyValues[$var];
}
public function __set( $val, $var ) {
echo "__set()ing:\n";
if ( ! in_array($this->arrSettables, $var) ) {
throw new Exception("$var is not settable.");
}
return $this->arrPropertyValues[$var];
}
} // end class declaration
class concrete extends abstraction {
public function __construct( $arrPropertyValues, $arrSettables, $arrGettables ) {
parent::__construct( $arrPropertyValues, $arrSettables, $arrGettables );
}
public function runTest() {
echo "Accessing array directly:\n";
$this->arrPropertyValues['color'] = "red";
echo "Color is {$this->arrPropertyValues['color']}.\n";
echo "Referencing property:\n";
echo "Color is {$this->color}.\n";
$this->color = "blue";
echo "Color is {$this->color}.\n";
$rand = "a" . mt_rand(0,10000000);
$this->$rand = "Here is a random value";
echo "'$rand' is {$this->$rand}.\n";
}
}
try {
$objBlock = & new concrete( array("color"=>"green"), array("color"), array("color") );
$objBlock->runTest();
} catch ( exception $e ) {
echo "Caught Exeption $e./n/n";
}
// no terminating delimiter
$ php test.php
Accessing array directly:
__get()ing:
Caught Exeption exception 'Exception' with message 'arrPropertyValues is not accessible.' in /var/www/test.php:23
Stack trace:
#0 /var/www/test.php(50): abstraction->__get('arrPropertyValu...')
#1 /var/www//test.php(68): concrete->runTest()
#2 {main}.
答案 0 :(得分:2)
有没有办法可以在使用__get()和__set()的php类中模拟公共和私有属性?
不直接(如果你打折debug_backtrace
)。
但是,您可以使用私有方法getPriv
执行当前__get
所做的所有工作。然后__get
将仅包装此私有方法并检查辅助功能。
function __get($name) {
if (in_array($name, $this->privateProperties))
throw new Exception("The property ". __CLASS__ . "::$name is private.");
return $this->getPriv($name);
}
在课堂上,您可以拨打getPriv
,从而绕过__get
。
答案 1 :(得分:1)
使abstraction::$arrPropertyValues
受保护或执行Artefacto所写的内容(如果您需要其他检查),但abstraction::getPriv()
应受到保护。
答案 2 :(得分:1)
您可以使用PHP繁琐的反射方法,而不是手动登记私有/受保护的属性:
function __get($name) {
$reflect = new ReflectionObject($this);
$publics = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);
if (in_array($name, $publics)) {
return $this->{$name};
}
}