Unserialize: примеры (PHP)
unserialize(string data [, array options]): mixedФункция unserialize преобразует сериализованную строку, созданную функцией serialize, обратно в PHP-значение.
Основная задача - восстановление данных (массивов, объектов, скалярных значений) из строкового представления. Часто используется для хранения сложных структур в базах данных, файлах или передаче между скриптами.
unserialize(string $data, array $options = []): mixed
Параметр $data: сериализованная строка для преобразования.
Параметр $options: ассоциативный массив опций (добавлен в PHP 7.0).
- allowed_classes (массив|логическое значение): определяет, какие классы можно инстанцировать.
true- все классы,false- ни один, массив - только указанные классы. - max_depth (целое число): максимальная глубина вложенности структур (с PHP 7.4).
Восстановление базовых типов данных:
$str = serialize(['apple', 'banana', 123]);
$arr = unserialize($str);
print_r($arr);
Array
(
[0] => apple
[1] => banana
[2] => 123
)
Использование флага allowed_classes:
class MyClass {}
$obj = new MyClass();
$serialized = serialize($obj);
// Запрет на восстановление объектов
$result = unserialize($serialized, ['allowed_classes' => false]);
var_dump($result);
object(__PHP_Incomplete_Class)#2 (1) {
["__PHP_Incomplete_Class_Name"]=>
string(7) "MyClass"
}
Ограничение по глубине вложенности:
$deepArray = [1 => [2 => [3 => [4 => 'deep']]]];
$serialized = serialize($deepArray);
$result = unserialize($serialized, ['max_depth' => 2]);
var_dump($result);
PHP Warning: unserialize(): Maximum depth of 2 reached. The data may be corrupted.
json_decode(): декодирование строки JSON. Работает быстрее для обмена данными с JavaScript, но не поддерживает сериализацию объектов PHP с методами (только данные).
$json = '{"name":"John", "age":30}';
$array = json_decode($json, true);
print_r($array);
Array
(
[name] => John
[age] => 30
)
msgpack_unpack(): распаковка данных из формата MessagePack. Более компактный и быстрый бинарный формат по сравнению с сериализацией PHP.
igbinary_unserialize(): альтернативная реализация сериализации, часто более эффективная по размеру и скорости.
import pickle
serialized = pickle.dumps(["hello", "world"])
unserialized = pickle.loads(serialized)
print(unserialized)
['hello', 'world']
В отличие от PHP, pickle по умолчанию выполняет код при десериализации объектов, что представляет угрозу безопасности.
let jsonString = '{"items": [1, 2, 3]}';
let obj = JSON.parse(jsonString);
console.log(obj.items);
[1, 2, 3]
В современных версиях JS также доступен structuredClone() для глубокого копирования сложных объектов.
Прямого аналога нет, но для хранения сериализованных данных PHP можно использовать колонки типа TEXT, а для извлечения - обычный SELECT.
Попытка десериализации данных из ненадёжного источника:
// Опасный код
$user_input = $_GET['data'];
$data = unserialize($user_input); // Уязвимость к инъекциям объектов
Игнорирование возврата false при ошибке:
$corrupted = 'a:1:{';
$result = unserialize($corrupted);
if ($result === false && $corrupted !== 'b:0;') {
echo 'Ошибка десериализации';
}
Ошибка десериализации
Проблемы с кодировкой или изменёнными данными:
$original = serialize('тест');
$modified = substr($original, 0, -1); // Повреждение строки
$result = @unserialize($modified);
var_dump($result);
bool(false)
PHP 7.0: добавлен второй параметр $options. Функция начала выбрасывать исключение Exception при обнаружении недопустимых классов, если allowed_classes установлен в false.
PHP 7.4: добавлена опция max_depth для защиты от переполнения стека.
PHP 8.0: поведение с некорректными данными стало более строгим. Улучшены сообщения об ошибках.
PHP 8.1: улучшена обработка сериализации специальных типов, таких как enum.
Использование магического метода __wakeup():
class User {
public $name;
public function __wakeup() {
echo 'Объект восстановлен. ';
}
}
$user = new User();
$user->name = 'Alice';
$serialized = serialize($user);
$restored = unserialize($serialized);
echo $restored->name;
Объект восстановлен. Alice
Обработка нескольких опций одновременно:
class A {}
class B {}
$data = serialize([new A(), new B()]);
$result = unserialize($data, [
'allowed_classes' => ['A'], // Только класс A разрешён
'max_depth' => 5
]);
print_r($result);
Array
(
[0] => A Object()
[1] => __PHP_Incomplete_Class Object
(
[__PHP_Incomplete_Class_Name] => B
)
)
Работа с пользовательскими обработчиками ошибок:
set_error_handler(function($errno, $errstr) {
throw new Exception($errstr);
});
try {
$result = unserialize('invalid data');
} catch (Exception $e) {
echo 'Перехвачена ошибка: ' . $e->getMessage();
}
restore_error_handler();
Перехвачена ошибка: unserialize(): Error at offset 0 of 12 bytes
Сравнение с альтернативной сериализацией:
$largeArray = range(1, 10000);
$phpSerialized = serialize($largeArray);
$jsonEncoded = json_encode($largeArray);
echo 'PHP serialize: ' . strlen($phpSerialized) . ' bytes';
echo 'JSON: ' . strlen($jsonEncoded) . ' bytes';
// Десериализация
$start = microtime(true);
$phpResult = unserialize($phpSerialized);
$phpTime = microtime(true) - $start;
$start = microtime(true);
$jsonResult = json_decode($jsonEncoded);
$jsonTime = microtime(true) - $start;
echo 'PHP unserialize time: ' . $phpTime;
echo 'JSON decode time: ' . $jsonTime;