php的动态代理的又一种实现

 
                 本来php4里,在对象内部是可以对$this赋值的(或许是bug)。但php5不让这样了,如果对$this赋值会引发一个fatel error:can not re-asign to $this。今天突然想到了一个办法。既然不让对$this赋值,那能不能绕个圈实现呢?
运行一下下面的代码
<?php
class Container {
    public $foo;
    function __construct() {
        $this->foo=new Proxy($this);
    }
}
class Proxy {
    private $container;
    function __construct(&$container) {
        $this->container=$container;
    }
    function go() {
        $this->container->foo=10;
    }
}
$c=new Container;
echo “开始n”;
echo ‘gettype($c->foo) = ”.gettype($c->foo).”‘n”;
echo ‘get_class($c->foo) = ”.get_class($c->foo).”‘n”;
echo “然后n”;
$c->foo->go();
echo ‘gettype($c->foo) = ”.gettype($c->foo).”‘n”;
echo ‘$c->foo = ‘.$c->foo.”n”;
?>
结果是:

开始
gettype($c->foo) = ‘object’
get_class($c->foo) = ‘Proxy’
然后
gettype($c->foo) = ‘integer’
$c->foo = 10

可以看到,$c->foo已经从一个Proxy对象变成了一个整数,而这一切是在对象内部完成的。这样,我们就可以做一个清爽的动态代理了。

class Container {
    var $p;
    function __construct() {
        $this->p=new Proxy($this,’p’,’Target’);
    }
}

class Target {
    var $v=777;
}

class Proxy {
    private $container;
    private $property;
    private $className;
    function __construct(&$container, $property, $class) {
        $this->container=&$container;
        $this->property=$property;
        $this->className=$class;
    }

    function __get($key) {
        $class=$this->className;
        $obj=new $class;
        $property=$this->property;
        $this->container->$property=$obj;
        return $obj->$key;
    }

    function __call($func, $arg) {
        $class=$this->className;
        $obj=new $class;
        $property=$this->property;
        $this->container->$property=$obj;
        return call_user_func_array(array($obj,$func), $arg);
    }
}

$c=new Container;
echo get_class($c->p).”n”;
echo $c->p->v.”n”;
echo get_class($c->p).”n”;
echo $c->p->v.”n”;
可以看到,使用代理和使用实际对象没有区别,而且当第二次访问的时候,$c->p已经变成了实际的对象了。

             

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s