我有数据库行包含序列化的对象。PHP反序列化一个没有匹配类的对象
我想反序列化这些,但类已经改变,一些属性变为私有,所以反序列化不再起作用。
有没有办法强制反序列化到数组或stdClass? (或任何在反序列化时不会导致错误的东西)
我想避免用脚本迁移数据。我宁愿与以旧格式序列化的对象具有向后兼容性。
我有数据库行包含序列化的对象。PHP反序列化一个没有匹配类的对象
我想反序列化这些,但类已经改变,一些属性变为私有,所以反序列化不再起作用。
有没有办法强制反序列化到数组或stdClass? (或任何在反序列化时不会导致错误的东西)
我想避免用脚本迁移数据。我宁愿与以旧格式序列化的对象具有向后兼容性。
不是真的,或者至少我会很害怕在生产中使用这样的东西。 但是,unserialize
将使用自动加载系统或unserialize_callback_func
ini设置中指定的函数名称。因此只要黑客就可以使这项工作:
// this a serialized object with the class "SomeMissingClass"
$str = 'O:16:"SomeMissingClass":1:{s:1:"a";s:1:"b";}';
ini_set('unserialize_callback_func', 'define_me'); // set your callback_function
// unserialize will pass in the desired class name
function define_me($classname) {
// just create a class that has some nice accessors to it
eval("class $classname extends ArrayObject {}");
}
$object = unserialize($str);
print $object['a']; // should print 'b'
您可以使用这样的事情将数据迁移到一点更加得心应手格式。
我已经与我的压抑的记忆对这个(我遇到这样的事情一次)协商,想起了其他的解决方案:
所以,你有你的SomeClass
与名为private
属性$a
class SomeClass {
private $a;
public function getA(){
return $this->a;
}
}
和你有它的序列化版本:
$str = 'O:9:"SomeClass":1:{s:1:"a";s:1:"b";}';
当你反序列化它,并转储结果会是这样的,这是没有好:
$a = unserialize($str);
var_dump($a->getA()); // prints 'null'
var_dump($a);
/*
prints:
object(SomeClass)#1 (2) {
["a":"SomeClass":private]=>
NULL
["a"]=>
string(1) "b"
}
*/
现在,当一个对象获取的反序列化,PHP将调用它的__wakeup
魔术方法。您需要的数据在对象中,但不在私有属性下,但是名称类似的公共名称。你无法到达,随着$this->a
,因为它会寻找错误的, 但是该方法get_object_vars()
将返回这些属性,你可以重新分配他们里面__wakeup()
:
class SomeClass {
private $a;
public function getA(){
return $this->a;
}
public function __wakeup(){
foreach (get_object_vars($this) as $k => $v) {
$this->{$k} = $v;
}
}
}
$str = 'O:9:"SomeClass":1:{s:1:"a";s:1:"b";}';
$a = unserialize($str);
print $a->getA();
我认为这是不用说,您应该为自己节省更多的头痛,并将您的数据转换为某种专用的数据交换格式。
哇,这很聪明,同时也是可怕的! – GordonM
感谢您的疯狂创意!这太棒了,我会用它轻松地迁移到一个比序列化对象更明智的数据格式:) –
除了手动调整数据库本身的数据本身,这总是一个风险主张,我认为你唯一的选择是将类代码回滚到旧版本,提取数据,然后将其重新存储在更明智的方式,可以在未来的代码修订中更轻松地处理。
你的SVN/GIT/CVS中有旧的类,对不对?
是的是的,我这样做,就像我说的我想避免迁移步骤*如果可能*。 –
不是讽刺或任何东西,但:*这是*为什么你不存储*代码*在数据库中...... :) – deceze
@deceze阿门到那。再也不! -_- –
这就是为什么你不把对象作为序列化字符串存储到数据库的原因。 – GordonM