PHP - 反序列化()期间的向后兼容性

时间:2021-04-13 12:57:29

标签: php serialization backwards-compatibility

我有一个应用程序,用户可以在其中将序列化的 PHP 对象保存在数据库中。 假设这是一个简单的游戏。 问题是:如果我更新了这个游戏并且用户会尝试加载他的存档怎么办? 假设我有一个这样的课程:

class Car {
   private Engine $engine;
   private array $wheels;
   private Color $color;
   private int $id;

   // methods ommitted, as they donesn't matter
}

假设某个用户创建了新车辆并保存在他的帐户中(作为数据库中的序列化文本)。 一段时间后,我决定重建这个类: 假设我将 $id 属性的名称更改为 $number,删除了 $wheels 属性,将 $engine 属性更改为 public 并添加了 $fuel 属性:

class Car {
    public Engine $engine;
    private Color $color;
    private int $number;
    private float $fuel;
}

如果用户现在尝试加载他的保存,unserialize() 函数将不起作用。

问题是:

如何解决?哪种方法最好?我应该在每次更新期间重建数据库中所有保存的数据吗?我应该在我的类中实现一些 __wakeup() 或 unserialize() 方法吗?怎么做?有没有好的方法/最佳实践/模式设计来解决这个问题?

// 更新: 好的,我找到了一些解决方案。我不知道这是否是一个好习惯,但它(几乎)有效: 在新的 Car 类中,我实现了一个 __wakeup() 方法,如下所示:

 public function __wakeup() {
     unset($this->wheels);
     $this->number = $this->id;
     unset($this->id);
 }

如您所见,第一行取消了 $wheels 的设置,因为该属性不再存在,接下来的两行将 $id 更改为 $number。 但是,这一行:

$this->number = $this->id;

产生错误:

Undefined property: Car::$id in ...

但是我可以在调试器和 var_dump 中看到这个变量的值:

object(Car)[1]
  public string 'color' => string 'yellow' (length=6)
  private string 'engine' => string 'V4' (length=2)
  private int 'number' => *uninitialized*
  private float 'fuel' => float 50
  private 'wheels' => 
    array (size=4)
      0 => string 'a' (length=1)
      1 => string 'b' (length=1)
      2 => string 'c' (length=1)
      3 => string 'd' (length=1)
  private 'id' => int 88

所以 id 存储在内存中的某个地方,但我不知道如何访问它。有什么想法吗?

0 个答案:

没有答案
相关问题