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.