Intereting Posts
php – настройка для часовых поясов Включить все функции в php-файл, который мне нужен, или только те функции, которые мне нужны? Выполнить код, когда модель Eloquent извлекается из базы данных как я могу использовать часовой пояс в фильтре даты Twig? Запустить php-функцию внутри jQuery Получение UDP-пакетных дейтаграмм в PHP Попытка создания URL-адресов с регулярным выражением PHP, японские символы не проходят Библиотеки / модели / лёгкие загрузки CodeIgniter Symfony2 с двумя вложенными динамическими полями формы Могу ли я использовать промежуточное программное обеспечение Laravel 5, чтобы позволить пакетам перекрывать маршруты приложений? Показывать текущий день посередине Значение POST становится нулевым после отправки формы Кэш-объект в PHP без использования сериализации Кто добавляет параметр _ _ "Single Underscore Query Parameter? Как автоматическое обновление данных в базе данных в PHP

PHP unserialize объекта без соответствующего класса

У меня есть строки базы данных, содержащие сериализованные объекты.

Я хочу их десериализовать, но класс изменился, некоторые свойства стали частными, поэтому десериализация перестала работать.

Есть ли способ заставить десериализацию массива или 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" } */ 

Теперь, когда объект get не является неэтериализованным, php будет называть его методом __wakeup magic. Необходимые данные есть в объекте, но не под частной собственностью, но с аналогичным названием public. Вы не можете достичь этого с помощью $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(); 

Я думаю, нет необходимости говорить, что вы должны сохранить себе дальнейшую головную боль и преобразовать свои данные в какой-то специальный формат обмена данными.

Помимо ручной обработки данных в самой базе данных, которая всегда является рискованным предложением, я думаю, что ваш единственный вариант – откат кода класса до более старой версии, извлечение данных, а затем повторное сохранение его более разумным образом, можно более легко рассмотреть в будущих версиях кода.

У вас есть старые классы в SVN / GIT / CVS, правильно?