unserialize () перестал работать после добавления интерфейса Serializable - PullRequest
0 голосов
/ 16 февраля 2019

У меня есть объект, который хранится в MySql с использованием serialize().

Теперь я обновил определение класса, заставив его реализовать интерфейс Serializable, и не могу десериализовать объект, потому что:

Erroneous data format for unserializing 'ClassName'

Метод отладки unserialize() этого класса не помогает - он даже не вызывается.

В качестве примера, скажем, у меня есть старость (A) и новое (B) объявление класса:

<?php

 class A {
     public $hello = "world";
 }

  class B implements Serializable {
     public $hello = "world";
     public function serialize() {}
     public function unserialize($serialized) { throw new Exception("test"); }
 }

теперь, когда я пытаюсь десериализовать данные:

$data1 = 'O:1:"A":1:{s:5:"hello";s:5:"world";}';
$data2 = 'O:1:"B":1:{s:5:"hello";s:5:"world";}';

var_dump(unserialize($data1));
var_dump(unserialize($data2));

Я получаю

object(A)#2 (1) {
  ["hello"]=>
  string(5) "world"
}
<br />
<b>Warning</b>:  Erroneous data format for unserializing 'B' in <b>[...][...]</b> on line <b>20</b><br />
<br />
<b>Notice</b>:  unserialize(): Error at offset 11 of 36 bytes in <b>[...][...]</b> on line <b>20</b><br />
bool(false)

1 Ответ

0 голосов
/ 17 февраля 2019

Проблема в том, что классы, реализующие Serializable, и классы, не реализующие интерфейс , используют другой формат сериализации .

Классы, которые не реализуют интерфейс, будут использовать "O нотацию":

O:1:"A":1:{s:5:"hello";s:5:"world";}

В то время как классы, реализующие Serializable, будут использовать «С нотацию».Ваш B класс serializaed будет выглядеть следующим образом:

C:1:"B":12:{s:5:"world";}

Десериализация просто не сработает, потому что вы пытаетесь отменить сериализацию до «неправильного» определения.

Это изменение произошлов 5.6 сообщалось как ошибка, и ответ был wontfix из-за последствий для безопасности старого поведения.

То, что вы пытаетесь сделать , работало только с PHP 5.3 до5.5 , насколько я могу судить.В документации упоминалось, что для классов, реализующих Serializable, метод __wakeup() был вызван перед вызовом unserialize(), но это было частью того, что было удалено в 5.6.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...