PHP使用Reflection类仍无法访问私有属性,求解决方案
如何在PHP类外部访问私有属性并解决Reflection使用后的报错问题
问题描述
尝试通过PHP Reflection类访问并修改类的私有属性pending_amount,修改完成后直接通过实例访问该属性时触发致命错误:
$ php src/Receipt.php PHP Fatal error: Uncaught Error: Cannot access private property TDD\Receipt::$pending_amount in C:\xampp\htdocs\all_scripts\PHPUnit_By_siddhu\src\Receipt.php:48 Stack trace: #0 {main} thrown in C:\xampp\htdocs\all_scripts\PHPUnit_By_siddhu\src\Receipt.php on line 48
原始测试代码:
<?php namespace TDD; class Receipt { public $user_id = 1; private $pending_amount = 45; public function total(array $items = []){ $items[] = $this->pending_amount; return array_sum($items); } public function tax($amount,$tax){ return $amount * $tax; } public function pending() { return $this->pending_amount = 45; } public function addTaxPending($tax){ return $this->pending_amount * $tax; } } $class = new \ReflectionClass('TDD\Receipt'); $myProtectedProperty = $class->getProperty('pending_amount'); $myProtectedProperty->setAccessible(true); $myInstance = new Receipt(); $myProtectedProperty->setValue($myInstance, 99); echo $myInstance->pending_amount; ?>
解决方案
错误的核心原因是:Reflection的setAccessible(true)仅允许Reflection API自身操作私有属性,并不会改变属性本身的访问权限,直接通过$实例->私有属性的方式依然违反PHP的封装规则,必须通过Reflection提供的方法读取属性值。
修改代码中读取属性的部分,使用ReflectionProperty的getValue()方法获取私有属性的值:
<?php namespace TDD; class Receipt { public $user_id = 1; private $pending_amount = 45; public function total(array $items = []){ $items[] = $this->pending_amount; return array_sum($items); } public function tax($amount,$tax){ return $amount * $tax; } public function pending() { return $this->pending_amount = 45; } public function addTaxPending($tax){ return $this->pending_amount * $tax; } } $class = new \ReflectionClass('TDD\Receipt'); $myProtectedProperty = $class->getProperty('pending_amount'); $myProtectedProperty->setAccessible(true); $myInstance = new Receipt(); $myProtectedProperty->setValue($myInstance, 99); // 替换直接访问为Reflection的getValue方法 echo $myProtectedProperty->getValue($myInstance); ?>
补充说明
如果只是需要读取私有属性,也可以简化流程:
$reflection = new \ReflectionClass($myInstance); $property = $reflection->getProperty('pending_amount'); $property->setAccessible(true); $value = $property->getValue($myInstance);
另外,在实际开发中,除非是单元测试、调试等特殊场景,不建议直接操作私有属性——类的私有属性设计初衷就是为了封装,直接破坏封装会降低代码的可维护性。
内容的提问来源于stack exchange,提问作者Siddhartha
相关产品推荐
相关产品推荐

