php中类外部访问类私有属性的方法

Eddy 发布于2013-8-17 17:28:17 分类: 知识积累 已浏览loading 网友评论0条 我要评论

我们都知道,类的私有属性在类外部是不可访问的,包括子类中也是不可访问的。比如如下代码:


<?php 
class Example1{
	private $_prop = 'test';
}

$r = function(Example1 $e){
	return $e->_prop;
};

$a = new Example1();
var_dump($r($a));

//运行结果:Fatal error: Cannot access private property Example1::$_prop
?>
但某些情况下我们需要访问类的私有属性,有下面这么几种方法可以实现:

1.利用反射


<?php 
class Example1{
	private $_prop = 'test';
}

$r = function(Example1 $e){
	return $e->_prop;
};

$a = new Example1();
$rfp = new ReflectionProperty('Example1','_prop');
$rfp->setAccessible(true);
var_dump($rfp->getValue($a));

//结果输出:string 'test' (length=4)
?>

2.利用Closure::bind()
此方法是php 5.4.0中新增的。


<?php 
class Example1{
	private $_prop = 'test';
}

$r = function(Example1 $e){
	return $e->_prop;
};

$a = new Example1();
$r = Closure::bind($r,null,$a);

var_dump($r($a));

//结果输出:string 'test' (length=4)
?>
另外,我们也可以用引用的方式来访问,这样我们就可以修改类的私有属性:

<?php 
class Example1{
	private $_prop = 'test';
}

$a = new Example1();
$r = Closure::bind(function & (Example1 $e) {
    return $e->_prop;
}, null, $a);

$cake = & $r($a);
$cake = 'lie';
var_dump($r($a));

//结果输出:string 'lie' (length=3)


据此,我们可以封装一个函数来读取/设置类的私有属性:

<?php
$reader = function & ($object, $property) {
    $value = & Closure::bind(function & () use ($property) {
        return $this->$property;
    }, $object, $object)->__invoke();

    return $value;
};
?>

Closure::bind()还有一个很有用之处,我们可以利用这一特性来给一个类动态的添加方法。官方文档中给了这么一个例子:


<?php
trait MetaTrait
{
	
	private $methods = array();
	
	public function addMethod($methodName, $methodCallable)
	{
		if (!is_callable($methodCallable)) {
			throw new InvalidArgumentException('Second param must be callable');
		}
		$this->methods[$methodName] = Closure::bind($methodCallable, $this, get_class());
	}
	
	public function __call($methodName, array $args)
	{
		if (isset($this->methods[$methodName])) {
			return call_user_func_array($this->methods[$methodName], $args);
		}
		
		throw RunTimeException('There is no method with the given name to call');
	}
	
}

class HackThursday {
	use MetaTrait;
	
	private $dayOfWeek = 'Thursday';
	
}

$test = new HackThursday();
$test->addMethod("addedMethod",function(){
	return '我是被动态添加进来的方法';
});

echo $test->addedMethod();

//结果输出:我是被动态添加进来的方法
?>

已经有(0)位网友发表了评论,你也评一评吧!
原创文章如转载,请注明:转载自Eddy Blog
原文地址:http://www.rrgod.com/skill/884.html     欢迎订阅Eddy Blog

记住我的信息,下次不用再输入 欢迎给Eddy Blog留言