百度空间 | 百度首页 
               
 
查看文章
 
冻结和解冻PHP对象
2008-12-02 20:59

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


类别:php语言 | 添加到搜藏 | 浏览() | 评论 (0)
 
最近读者:
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu