2013-06-27 38 views
2

我有数据库行包含序列化的对象。PHP反序列化一个没有匹配类的对象

我想反序列化这些,但类已经改变,一些属性变为私有,所以反序列化不再起作用。

有没有办法强制反序列化到数组或stdClass? (或任何在反序列化时不会导致错误的东西)

我想避免用脚本迁移数据。我宁愿与以旧格式序列化的对象具有向后兼容性。

+2

不是讽刺或任何东西,但:*这是*为什么你不存储*代码*在数据库中...... :) – deceze

+0

@deceze阿门到那。再也不! -_- –

+0

这就是为什么你不把对象作为序列化字符串存储到数据库的原因。 – GordonM

回答

5

不是真的,或者至少我会很害怕在生产中使用这样的东西。 但是,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' 

您可以使用这样的事情将数据迁移到一点更加得心应手格式。

UPDATE:

我已经与我的压抑的记忆对这个(我遇到这样的事情一次)协商,想起了其他的解决方案:

所以,你有你的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(); 

我认为这是不用说,您应该为自己节省更多的头痛,并将您的数据转换为某种专用的数据交换格式。

+1

哇,这很聪明,同时也是可怕的! – GordonM

+0

感谢您的疯狂创意!这太棒了,我会用它轻松地迁移到一个比序列化对象更明智的数据格式:) –

-1

除了手动调整数据库本身的数据本身,这总是一个风险主张,我认为你唯一的选择是将类代码回滚到旧版本,提取数据,然后将其重新存储在更明智的方式,可以在未来的代码修订中更轻松地处理。

你的SVN/GIT/CVS中有旧的类,对不对?

+0

是的是的,我这样做,就像我说的我想避免迁移步骤*如果可能*。 –

相关问题