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