本来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";
?>
结果是: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已经变成了实际的对象了。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";
来源:http://syre.blogbus.com/logs/1882118.html
作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/2832/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!
最后编辑: jackxiang 编辑于2010-3-17 16:57
评论列表