academe / serializeparser
一个用于处理序列化数据的PHP解析器,能够查看序列化字符串。
1.0.2
2017-02-27 12:16 UTC
Requires
- php: >=5.4.0
Requires (Dev)
- phpunit/phpunit: ~4.0
This package is auto-updated.
Last update: 2024-09-23 04:27:18 UTC
README
SerializeParser
一个用于处理序列化数据的PHP解析器,能够查看序列化字符串。
目的
我在数据库中有一批PHP序列化数据,需要检查这些数据以向管理员展示信息。看起来没有在PHP中解释这些数据的方法,不需要实例化数据中的所有对象,而且我也没有所有类的可用。
有一个设置可以让你用一个类替换缺失的类,但这仍然意味着实例化那些可能存在的类。
因此,这里有一个简单的解析器,它接受一个序列化数据字符串,并尝试将其反序列化,但用stdClass
替换所有对象,这样我们就不需要实例化那些无权被实例化的类,或者那些可能根本不存在的应用程序中的类。
如何使用
这是一个简单的例子
// Create a complex array/object/string/number/boolean to serialize. $obj = new \Academe\SerializeParser\StringReader('xyz'); $obj->foo = true; $data = [ 'a' => 1, [ 'foo' => 'bar', $obj, 'b' => false, ], ]; $serialized = serialize($data); // Take a look a how PHP has serialised it. echo $serialized; // a:3:{s:1:"a";i:1;i:0;a:3:{s:3:"foo";s:3:"bar";i:0;O:36:"Academe\SerializeParser\StringReader":4:{s:6:"*pos";i:0;s:6:"*max";i:2;s:9:"*string";s:3:"xyz";s:3:"foo";b:1;}i:1;O:7:"myClass":2:{s:12:"*protected";s:4:"prot";s:16:"myClassprivate";s:4:"priv";}}s:1:"b";b:0;} // Somewhat beautified: /* a:3:{ s:1:"a";i:1; i:0;a:3:{ s:3:"foo";s:3:"bar"; i:0;O:36:"Academe\SerializeParser\StringReader":4:{ s:6:"*pos";i:0; s:6:"*max";i:2; s:9:"*string";s:3:"xyz"; s:3:"foo";b:1; } i:1;O:7:"myClass":2:{ s:12:"*protected";s:4:"prot"; s:16:"myClassprivate";s:4:"priv"; } } s:1:"b";b:0; } */ // Now parse it to look at what it inside, without instantiating the // original objects in it. $parser = new \Academe\SerializeParser\Parser; $parsed = $parser->parse($serialized); var_dump($parsed); /* array(3) { ["a"]=> int(1) [0]=> array(3) { ["foo"]=> string(3) "bar" [0]=> object(stdClass)#6 (5) { ["__class_name"]=> string(36) "Academe\SerializeParser\StringReader" ["pos"]=> int(0) ["max"]=> int(2) ["string"]=> string(3) "xyz" ["foo"]=> bool(true) } [1]=> object(stdClass)#7 (3) { ["__class_name"]=> string(7) "myClass" ["protected"]=> string(4) "prot" ["private"]=> string(4) "priv" } } ["b"]=> bool(false) } */
注意,StringReader
类已被反序列化为stdClass
,原始名称已移动到属性__class_name
。受保护和私有的属性也全部存在并可访问(尽管最终解析的结构没有显示哪些是受保护的或私有的——也许可以有一个元数据属性来列出这些?)。
记住,这个的目的不是重建原始数据作为准确的表现。这是允许数据被检查并提取一些关键值以进行日志记录、向用户展示等。
待办事项
- 可能使
Parser::parse()
方法成为静态。 - 使StringReader更高效。效率不是这个工作关键。
- 注入字符串读取器,以便在测试中模拟。
想要帮助吗?
如果你喜欢编写一些测试,发现了一个错误,或者可以扩展它以处理更多序列化数据的情况,那么请随意参与。PR、问题或只是给我发电子邮件——你喜欢什么就做什么。
源规范
序列化工作的唯一源规范是PHP源代码。然而,有大量的序列化解析器是为除PHP之外的语言编写的,它们是有效的,并且是从该代码派生出来的。我已经将这些代码从一些这些包中移植过来。
这还不是完整的,所以不会处理引用,但足以满足我的需求。
- 这是一个有用的Python算法
https://github.com/jqr/php-serialize/blob/master/lib/php_serialize.rb#L195 - 这里有一些关于细节的相当好的描述
http://stackoverflow.com/questions/14297926/structure-of-a-serialized-php-string - 我最初的SO问题引导我编写了自己的解决方案
http://stackoverflow.com/questions/31219158/analyse-parse-a-serialized-php-data-containing-objects/31223873 - PHP内部书籍的这一部分对所有数据类型进行了很好的分解
http://www.phpinternalsbook.com/classes_objects/serialization.html