PHP反射API组成部分ReflectionProperty类中的setAccessible()方法是PHP 5.3众多新特性中的一项。该方法使得类或对象的protected和private字段可以被 ReflectionProperty::getValue()和ReflectionProperty::setValue()方法访问,从而将protected和private字段的读写完全开放给外界。
新特性加强了PHP元编程能力,在众多用法中,其中之一是开发者可以利用它定制对象的串行化,如下面概念验证性代码所示 :
-
<?php
class Object_Freezer
{
public static function freeze($object)
{
$state = array();
$reflector = new ReflectionObject($object);
foreach ($reflector->getProperties() as $attribute) {
$attribute->setAccessible(TRUE);
$state[$attribute->getName()] =
$attribute->getValue($object);
}
return array(
'className' => get_class($object), 'state' => $state
);
}
public static function thaw(array $frozenObject)
{
if (!class_exists($frozenObject['className'])) {
throw new RuntimeException(
sprintf(
'Class "%s" could not be found.',
$frozenObject['className']
)
);
}
$object = unserialize(
sprintf(
'O:%d:"%s":0:{}',
strlen($frozenObject['className']),
$frozenObject['className']
)
);
$reflector = new ReflectionObject($object);
foreach ($frozenObject['state'] as $name => $value) {
$attribute = $reflector->getProperty($name);
$attribute->setAccessible(TRUE);
$attribute->setValue($object, $value);
}
return $object;
}
}
?>
下面代码片段使用上面的Object_Freezer类“冻结”和“解冻”一个对象:
-
<?php
require 'Object/Freezer.php';
class Foo
{
public $a;
protected $b;
private $c;
public function __construct($a, $b, $c)
{
$this->a = $a;
$this->b = $b;
$this->c = $c;
}
}
$object = new Foo(1, 2, 3);
var_dump($object);
$frozenObject = Object_Freezer::freeze($object);
var_dump($frozenObject);
$object = Object_Freezer::thaw($frozenObject);
var_dump($object);
?>
下面是上面代码的输出:
object(Foo)#1 (3) {
["a"]=>
int(1)
["b":protected]=>
int(2)
["c":"Foo":private]=>
int(3)
}
array(2) {
["className"]=>
string(3) "Foo"
["state"]=>
array(3) {
["a"]=>
int(1)
["b"]=>
int(2)
["c"]=>
int(3)
}
}
object(Foo)#5 (3) {
["a"]=>
int(1)
["b":protected]=>
int(2)
["c":"Foo":private]=>
int(3)
}
原文链接:http://sebastian-bergmann.de/archives/831-Freezing-and-Thawing-PHP-Objects.html