leedavis81 / altr-ego
访问对象受保护/私有属性和方法
v1.0.2
2013-07-25 17:43 UTC
Requires
- php: >=5.3.3
Requires (Dev)
- phpunit/phpunit: 3.7.*
This package is not auto-updated.
Last update: 2024-09-23 11:32:44 UTC
README
一个工具,允许您通过破坏PHP作用域来访问对象的受保护/私有属性。这在测试场景中非常有用,您想快速验证应用程序中隐藏的封装过程。通常,当您只想测试应用程序的某个小部分时,该过程可以(正确地)封装并设置为私有/保护。并且无法从您的测试套件中调用。运行创建、模拟和注入依赖以使对象处于测试有效状态的流程可能非常耗时。这个工具可以帮助您直接调用该私有过程或检查该受保护属性。
AltrEgo允许您在任意操作过程中完全保持对象的状态。如果您决定希望作用域重新生效,您只需重新获取对象。在其作为“AltrEgo”对象的时间期间所做的任何更改都将保持不变。
此库使用适配器来适配不同版本的PHP。
如果您正在使用5.3
那么将使用PHP的Reflection类来破坏您对象的作用域。
对于5.4,此库使用闭包作用域绑定
PHP 5.4使用闭包提供了新的“作用域破坏”功能。请参阅Davey Shafik的闭包谜题博客文章,以了解此功能的工作原理。此方法比使用PHP的内置反射工具快得多。我进行的“破坏作用域”测试表明,速度提高了大约52%。
用法
// Given the following class (nice and private all round) class Foo { private $priv = 'This is a private variable'; private $privArray = array('private array entry'); private function privFunc($value) { return $value; } private static function privStatFunc($value) { return $value; } } // We first off create an alter ego $alterEgo = AltrEgo::create(new Foo()); // Right, now lets get a hook on those private bits echo $alterEgo->priv . PHP_EOL; // Output: This is a private variable // Woot, works, now lets set it to something else and see what happens $alterEgo->priv = 'new private value'; echo $alterEgo->priv . PHP_EOL; // Output: new private value // This value remains on your object, even after retrieving it back with $alterEgo->getObject() // now lets try some method calls echo $alterEgo->privFunc('Private call') . PHP_EOL; //Output: Private call // Now then, onto arrays; You can pass in an array of parameters like so: var_dump($alterEgo->privFunc('Private', 'call')); /** Output: array(2) { [0]=> string(7) "Private" [1]=> string(4) "call" } */ // You can push values straight into them using standard PHP array syntax. // But be aware, the array will be converted (and maintained) as an ArrayObject $alterEgo->privArray[] = 'new value'; var_dump($alterEgo->privArray); /** Output: object(ArrayObject)#5 (1) { ["storage":"ArrayObject":private]=> array(2) { [0]=> string(19) "private array entry" [1]=> string(9) "new value" } } */ // You can add associative array values and unset them as you normally would in PHP $alterEgo->privArray['assoc_key'] = 'private key value entry'; var_dump($alterEgo->privArray); unset($alterEgo->privArray['assoc_key']); var_dump($alterEgo->privArray); /** Output: object(ArrayObject)#5 (1) { ["storage":"ArrayObject":private]=> array(3) { [0]=> string(19) "private array entry" [1]=> string(9) "new value" ["assoc_key"]=> string(23) "private key value entry" } } object(ArrayObject)#5 (1) { ["storage":"ArrayObject":private]=> array(2) { [0]=> string(19) "private array entry" [1]=> string(9) "new value" } } */ // We also have the facility to execute static function that have private/protected visibility. // It's rare you'll ever come across these, they're typically set as public so you'd normally call them directly echo AltrEgo::callStatic($alterEgo, 'privStatFunc', 'private static call') . PHP_EOL; // Output: private static call // Also works with arrays var_dump(AltrEgo::callStatic($alterEgo, 'privStatFunc', array('private', 'static', 'call'))); /** Output: array(3) { [0]=> string(7) "private" [1]=> string(6) "static" [2]=> string(4) "call" } */ // If at anytime you want to jump back into scope just fetch your object back. // You can throw it back into AltrEgo::create() whenever you need $backToScope = $alterEgo->getObject();
局限性
- 在访问数组属性时,它将被转换为(并维护)ArrayObject。这是由于使用PHP重载(__get)设置数组值时的限制。如果您遇到问题,可以直接获取值,然后用修改后的值覆盖它。或者一旦您检索到修改后的ArrayObject,只需对其运行 ->toArray()。