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

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

<?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($methodNamearray $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(); 
 
//结果输出:我是被动态添加进来的方法 
?> 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值