Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP-取消序列化()期间的向后兼容性_Php_Serialization_Backwards Compatibility - Fatal编程技术网

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

PHP-取消序列化()期间的向后兼容性,php,serialization,backwards-compatibility,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 mat

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

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

   // methods ommitted, as they donesn't matter
}
 public function __wakeup() {
     unset($this->wheels);
     $this->number = $this->id;
     unset($this->id);
 }
假设某个用户创建了新的车辆并将其保存在其帐户中(作为数据库中的序列化文本)。 一段时间后,我决定重建这个类: 假设我将$id属性的名称更改为$number,删除了$wheels属性,将$engine属性更改为public,并添加了$fuel属性:

class Car {
    public Engine $engine;
    private Color $color;
    private int $number;
    private float $fuel;
}
如果用户现在尝试加载他的save,unserialize()函数将不起作用

问题是:

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

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

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

   // methods ommitted, as they donesn't matter
}
 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 ...
但是,我可以在debbugger和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存储在内存中的某个地方,但我不知道如何访问它。有什么想法吗?

“我应该在每次更新期间重建数据库中保存的所有数据吗?”-这显然是最可靠的解决方案。这样,转换只需进行一次。您是否应该开始查看一些数据库库(Elount、doctrine等)以在数据库中存储数据。这是一个在DB中使用原子值进行设计并使用某种ORM将DB行映射到类/模型的极好示例。否则,您需要创建一个自定义解决方案,用于将序列化数据映射到类并对其进行修改。您之所以会遇到这些问题,是因为您使用了一种次优的存储方式。如果需要,跨数据库表分布的数据更容易转换。