This is my first question on SO, though I've searched substantially; I apologize if this has already been touched on.
The question/issue has to do with PHP's serialize() functionality. I am using serialization to store objects in a database. For example:
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";}}
Now, later on in the project life, I want to modify my class, First, to have a new property: $SomethingElse that will also correspond to a Something object.
The question is, for my old/existing objects, when I unserialize to the new version of my First class, it seems that the only way to initialize the new property (SomethingElse) is to look for it in the __wakeup() method. In which case, I need to document any new properties there. Is this correct? Properties need to be treated as in the constructor, having their initial value set (which ultimately duplicates the code).
I find that if I initalize the variable when declaring it, then it will get picked up by unserialize, for example, if I changed the Something class to:
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. ) )
But you cannot initialize new properties to objects when declaring them, is has to be done in the constructor (and __wakeup()?).
I hope I explained this well enough. I want to know if there's some programming pattern around this that I am missing, or if duplicating initialization code (or referencing an init method) in __wakeup() is typical, or if I simply need to be prepared to migrate old objects to new versions via. migration scripts.
Thanks.
Update: In thinking about what was said by the commenters so far, I thought I'd post the updated First class with an init() method:
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 ) )
So really I'm not sure, because that seems like a workable pattern to me. As classes gain new properties they take their default values upon first restoration.
Good question! It cannot been answered in general. And I would say, that's not just related to serialize().. When you have a SQL database, and your code changes it will not work with old data too. That's a common problem of version management with data (bases).
When integrating data from an older software version into a newer one, you'll mostly have the problem that old data has to be translated into a newer format. That's even true with config files etc...
It is usual to write a script that translates the old data into the new format in such cases. I've done this a couple of years at work when creating upgrade packages for a PHP 'firmware' of a server product. :) And so do the most package managers on Linux distributions.
Note: If you will be safe against data loss between upgrades you'll have to take care during development and have the 'upgradability' of data in mind.
Update: I think serialized data can make the update process of data even worse. What is if you serialize a class and the rename it? will be hard to retrieve the data. I never thought about this but it sounds like a problem in case of version upgrades.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With