本文介绍了使用__get()和__set()模拟公共/私有属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个使用__get()__set()在主数组中存储和检索数组元素的类.我进行了检查,使某些元素变得无法获取,基本上是重新创建了私有属性.

I was writing a class that uses __get() and __set() to store and retrieve array elements in a master array. I had a check to make some elements ungettable, basically to re-create private properties.

我注意到,似乎__get拦截了所有对类属性的调用.这对我来说很烂,因为我想拥有一个外部私有的变量(无法通过get获得),但是我试图通过直接从类内部引用master数组来访问它.当然,主数组不在gettable属性的白名单中:(

I noticed that it seemed that __get intercepts all calls to class properties. This sucks for me, because I wanted to have a variable private to the outside world ( unavailable via get ), but I was trying to access it by directly referencing the master array from within the class. Of course, the master array is not in the whitelist of gettable properties :(

是否可以在使用__get()__set()的php类中模拟公共属性和私有属性?

Is there a way I can emulate public and private properties in a php class that uses __get() and __set()?

示例:

<?
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}.

推荐答案

不直接(如果您打折 debug_backtrace ).

Not directly (if you discount debug_backtrace).

但是您可以有一个私有方法getPriv,它可以完成当前__get的所有工作.然后__get将只包装此私有方法并检查可访问性.

But you can have a private method getPriv that does all the work your current __get does. Then __get would only wrap this private method and check accessibility.

function __get($name) {        
    if (in_array($name, $this->privateProperties))
        throw new Exception("The property ". __CLASS__ . "::$name is private.");
    return $this->getPriv($name);
}

在您的班级中,您将调用getPriv,从而绕过__get.

Inside your class, you would call getPriv, thus bypassing __get.

这篇关于使用__get()和__set()模拟公共/私有属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-17 20:33