这是我关于SO的第一个问题,尽管我已经进行了大量搜索;如果已经触及,我道歉。
问题/问题与PHP的serialize()功能有关。我正在使用序列化将对象存储在数据库中。例如:
class Something {
public $text = "Hello World";
}
class First {
var $MySomething;
public function __construct() {
$this->MySomething = new Something();
}
}
$first_obj = new First();
$string_to_store = serialize($first_obj);
echo $string_to_store
// Result: O:5:"First":1:{s:11:"MySomething";O:9:"Something":1:{s:4:"text";s:11:"Hello World";}}
现在,在项目生命的后期,我想修改我的类,首先,要有一个新属性:$ SomethingElse,它也将对应于Something对象。
问题是,对于我的旧/现有对象,当我反序列化到我的First类的新版本时,似乎初始化新属性(SomethingElse)的唯一方法是在__wakeup()中查找它方法。在这种情况下,我需要在那里记录任何新属性。 这是正确的吗?属性需要像构造函数一样对待,设置初始值(最终会复制代码)。
我发现如果我在声明变量时将其变为初始化,那么它将通过反序列化来获取,例如,如果我将Something类更改为:
class Something {
public $text = "Hello World";
public $new_text = "I would be in the unserialized old version.";
}
...
$obj = unserialize('O:5:"First":1:{s:11:"MySomething";O:9:"Something":1:{s:4:"text";s:11:"Hello World";}}');
print_r($obj);
// Result: First Object ( [MySomething] => Something Object ( [text] => Hello World [new_text] => I would be in the unserialized old version. ) )
但是在声明它们时你无法初始化对象的新属性,是否在构造函数中完成(和__wakeup()?)。
我希望我解释得这么好。我想知道是否有一些我遗漏的编程模式,或者在__wakeup()中复制初始化代码(或引用init方法)是典型的,或者我只是需要准备将旧对象迁移到新版本通过。迁移脚本。
感谢。
更新:在考虑到目前为止评论者所说的内容时,我想我会用init()方法发布更新的First类:
class Something {
public $text = "Hello World2";
public $new_text = "I would be in the unserialized old version.2";
}
class First {
var $MySomething;
var $SomethingElse;
public function __construct() {
$this->init();
}
public function __wakeup() {
$this->init();
}
private function init() {
if (!isset($this->MySomething)) {
$this->MySomething = new Something();
}
if (!isset($this->SomethingElse)) {
$this->SomethingElse = new Something();
}
}
}
$new_obj = unserialize('O:5:"First":1:{s:11:"MySomething";O:9:"Something":1:{s:4:"text";s:11:"Hello World";}}');
print_r($new_obj);
// Result: First Object ( [MySomething] => Something Object ( [text] => Hello World [new_text] => I would be in the unserialized old version.2 ) [SomethingElse] => Something Object ( [text] => Hello World2 [new_text] => I would be in the unserialized old version.2 ) )
所以我真的不确定,因为这对我来说似乎是一种可行的模式。当类获得新属性时,它们会在首次恢复时使用其默认值。
答案 0 :(得分:2)
好问题!一般来说,它无法回答。我会说,这不仅仅与serialize()有关。当你有一个SQL数据库,并且你的代码发生了变化时,它也无法使用旧数据。这是使用数据(基础)进行版本管理的常见问题。
将较旧软件版本的数据整合到较新版本中时,您将面临的问题是旧数据必须转换为更新的格式。对于配置文件等,情况确实如此......
通常编写一个脚本,在这种情况下将旧数据转换为新格式。在为PHP'固件创建升级包时,我已经在工作了几年。服务器产品:) Linux发行版上的大多数软件包管理器也是如此。
注意:如果您可以安全地防止升级之间的数据丢失,那么您在开发过程中必须注意并具有“可升级性”。记住数据。
更新:我认为序列化数据可能会使数据的更新过程更加糟糕。如果序列化一个类并将其重命名,该怎么办?将很难检索数据。我从来没有想过这个,但在版本升级的情况下,它听起来像一个问题。
答案 1 :(得分:0)
上次我有一个更改属性的类时,我将所有数据存储在一个名为$ classVar的关联数组中。如果这样做,那么无论您添加多少个变量,都会使用一个简单的序列化调用来跟踪您添加的所有变量。
在使用方面,只需检查变量是否已初始化,如果不是,请设置默认值。您甚至可以序列化一个classversion变量来处理更复杂的情况,例如不再使用的变量或需要转换的变量