使用新的类名不匹配属性反序列化类

时间:2018-12-21 17:28:28

标签: php

我们已经序列化了存储在数据库中的类,我们正尝试使用新的psr 4类名进行反序列化。当我们运行反序列化功能时,无法正确创建该类。

新旧类是相同的,唯一真正改变的是名称从psr 0类名称到psr 4类不同。反序列化时,请确保使用class_alias将序列化代码中存储的旧类指向新类。反序列化时没有出现任何错误,但类属性未正确设置。

例如,我们正在使用序列化类Company_Shipping。我们将该类的别名别名为Company\Shipping,但是当我们转储对象时,我们会得到属性

  

private'_method'=>空

     

private'_method'(Company_Shipping)=>字符串'ground'(长度= 6)

我们应该得到

  

private'_method'=>字符串'ground'(长度= 6)

那么,有一种方法可以使用方括号中的旧类名称访问第二个私有属性?如果可以的话,我可以在__wake方法中传输属性,但是我不知道如何访问它们。但是,如果有人知道如何解决此反序列化问题,那就太好了。

2 个答案:

答案 0 :(得分:0)

问题是,所有私有属性都以完整的合格类名作为前缀-如果您使用别名,则无法解决。

您可以使用多个选项来解决此问题-但是大多数都无法使用现有数据。

  1. 选项(仅一个,可用于您现有的数据):更新序列化的字符串。如果您不存储复杂数据,则可以使用preg_replace_callback和此正则表达式\bs:([0-9]+):"([^"]+)"来完成。然后将是replace回调的任务,以更新长度(第一个匹配组)和类名+字段(第二个匹配组)。

  2. 选项:将所有private字段设为publicprotected。这样做将来不会对序列化造成任何问题。

  3. 选项:使类实现Serializable接口。在这种情况下,您有两种方法(serializeunserialize),它们进行序列化并可以与任何字符串一起使用。在这种情况下,您可以在serialize中返回一个包含所有字段的序列化数组,并在unserialize方法中,必须重新分配该值。

答案 1 :(得分:0)

这是一个很好的学习机会,了解private为何过高。如果属性仅是protected,则可以声明:

class Company_Shipping extends Company\Shipping {}

并且没有序列化也没有问题。

在这一点上,我想说,最好的选择是在应用程序中保留旧版Company_Shipping对象代码的副本,编写一些代码以将Company_Shipping转换为Company\Shipping, [这又比需要困难,因为private],然后将所有存储的对象显式重新编码为新格式,或者插入各种垫片以快速检测和转换它们。