note 103744 deleted from function.unserialize by aharvey
| From: | aharvey@php.net | Date: | Tue, 06 Nov 2012 01:38:33 +0000 |
| Subject: | note 103744 deleted from function.unserialize by aharvey | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-191727@lists.php.net to get a copy of this message | ||
Note Submitter: i dot chiriac at yahoo dot com
----
Hi,
I'm working with serialized objects stored on files and I've found a problem and his fix
when you modify the serialized object subclassing. When you serialize a class with a private
property, the subclassing of this private property will simply not work because each private
property is attached to it's class level.
For example, you start to implement and serialize this class :
<?php
class bar {
private $var = 'bar value';
public function getValue() {
return $this->var;
}
}
?>
You store an instance of the bar class into a file as a serialized string.
After some code refactoring you prefer to store the value in a subclass like this :
<?php
class foo {
private $var = 'bar value';
public function getValue() {
return $this->var;
}
}
class bar extends foo {
}
?>
When you retrieve the stored bar instance from the srialized file, you have lose the $var value.
The only solution is to store private vars as protected properties and not private ones.
If you want to migrate/convert serialized private values as protected values you can use the
following code :
<?php
function setProtected($serialized, $vars) {
if ($serialized[0] != 'O') {
throw new Exception('The serialized string is not representing a class');
}
$size = '';
for($i = 2; $i < strlen($serialized); $i++) {
if ($serialized[$i] == ':') break;
$size .= $serialized[$i];
}
$class = substr($serialized, $i + 2, $size);
$find = array();
$replace = array();
foreach($vars as $name) {
$from = chr(0).$class.chr(0).$name;
$to = chr(0).'*'.chr(0).$name;
$find[] = 's:'.strlen($from).':"'.$from.'";';
$replace[] = 's:'.strlen($to).':"'.$to.'";';
}
return str_replace($find, $replace, $serialized);
}
// example of use
$obj = unserialize(
setProtected(
file_get_contents('object.ser'),
array('property1', 'propetyN')
)
);
?>
Hope this will helps someone,
aKhEnAtHoN