PHP在没有匹配类的情况下反序列化对象

Mat*_*oli 3 php serialization

我有包含序列化对象的数据库行.

我想反序列化这些,但是类已经改变,一些属性变得私有,因此反序列化不再起作用.

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

我想避免使用脚本迁移数据.我宁愿向后兼容旧格式序列化的对象.

com*_*857 6

不是真的,或者至少我会害怕在生产中使用这样的东西.但是,unserialize将使用自动加载系统或unserialize_callback_funcini设置中指定的功能名称.所以通过一点点黑客攻击你可以做到这一点:

// 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'
Run Code Online (Sandbox Code Playgroud)

您可以使用类似的东西将数据迁移到更方便的格式.

更新:

我已经就此对我压抑的记忆进行了咨询(我曾经遇到过这样的事情),还记得另一个解决方案:

所以你有SomeClass一个private名为的财产$a

class SomeClass {
    private $a;
    public function getA(){
        return $this->a;
    }
}
Run Code Online (Sandbox Code Playgroud)

你有它的序列化版本:

$str = 'O:9:"SomeClass":1:{s:1:"a";s:1:"b";}';
Run Code Online (Sandbox Code Playgroud)

当你反序列化它,并转储结果时它看起来像这样,这是不好的:

$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"
}
*/
Run Code Online (Sandbox Code Playgroud)

现在,当一个对象被反序列化时,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();
Run Code Online (Sandbox Code Playgroud)

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