PHP desserializar un objeto sin la clase correspondiente

Tengo filas de bases de datos que contienen objetos serializados.

Quiero deserializar estos, pero la clase ha cambiado, algunas propiedades se han privado, por lo que la deserialización ya no funciona.

¿Hay alguna manera de forzar la deserialización a una matriz o una stdClass? (o cualquier cosa que no cause un error al deserializarse)

Quiero evitar la migración de datos con un script. Prefiero compatibilidad hacia atrás con los objetos serializados en el formato anterior.

En realidad, no, o al menos tendría mucho miedo de usar algo como esto en la producción. Sin embargo, unserialize utilizará el sistema de carga automática o el nombre de función especificado en la configuración ini unserialize_callback_func . Entonces con un poco de pirateo puedes hacer que esto funcione:

 // 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' 

Puede usar algo como esto para migrar sus datos a un formato un poco más práctico.

ACTUALIZAR:

He consultado sobre mis recuerdos reprimidos sobre esto (me he enfrentado a algo así una vez) y recordé otra solución:

Entonces tienes tu SomeClass con una propiedad private llamada $a

 class SomeClass { private $a; public function getA(){ return $this->a; } } 

Y tienes la versión serializada de esto:

 $str = 'O:9:"SomeClass":1:{s:1:"a";s:1:"b";}'; 

Cuando lo extratermine, y volque el resultado, se verá así, lo cual no es bueno:

 $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" } */ 

Ahora, cuando un objeto get se desserializa, php lo llamará método de magia __wakeup . Los datos que necesita están allí en el objeto, pero no en la propiedad privada, sino en uno público de nombre similar. No puede alcanzar eso con $this->a ya que buscará el incorrecto, sin embargo, el método get_object_vars() devolverá estas propiedades y podrá reasignarlas dentro de un __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(); 

Creo que es innecesario decir que debe ahorrarse más dolores de cabeza y convertir sus datos a algún formato de intercambio de datos dedicado.

Además de manipular manualmente los datos en la base de datos, lo que siempre es una propuesta arriesgada, creo que tu única opción es retrotraer el código de clase a una versión anterior, extraer los datos, luego volver a almacenarlos de una manera más sensata que se puede tratar más fácilmente en futuras revisiones de código.

Tienes las clases antiguas en tu SVN / GIT / CVS, ¿verdad?