Сериализация объектов в PHP: полное руководство
Сериализация — это процесс преобразования сложных структур данных (объектов, массивов) в строку или бинарный формат, который можно сохранить в файл, передать по сети или кэшировать. В PHP этот механизм реализован встроенными функциями serialize() и unserialize(). В этой статье мы подробно разберём, как работает сериализация объектов, какие подводные камни существуют и как использовать магические методы для тонкой настройки процесса.
Основные функции сериализации
PHP предоставляет две ключевые функции для работы с сериализацией:
serialize($value)— преобразует значение (кроме resource) в строку, пригодную для хранения. Для объектов сохраняется имя класса и все свойства (включая приватные и защищённые).unserialize($string)— восстанавливает исходное значение из строки. Для объектов автоматически вызывается конструктор класса (если он определён) и подставляются сохранённые свойства.
Простой пример сериализации объекта
Рассмотрим базовый класс User и его сериализацию:
<?php
class User {
public $name;
public $email;
private $password;
public function __construct($name, $email, $password) {
$this->name = $name;
$this->email = $email;
$this->password = $password;
}
}
$user = new User('Иван', 'ivan@example.com', 'secret123');
$serialized = serialize($user);
echo $serialized;
// Вывод: O:4:"User":3:{s:4:"name";s:8:"Иван";s:5:"email";s:16:"ivan@example.com";s:12:"\0User\0password";s:9:"secret123";}
?>
Обратите внимание: приватное свойство $password в строке выглядит как \0User\0password — это специальное обозначение для приватных полей, где \0 — нулевой байт.
Восстановление объекта из сериализованной строки
<?php
$serialized = 'O:4:"User":3:{s:4:"name";s:8:"Иван";s:5:"email";s:16:"ivan@example.com";s:12:"\0User\0password";s:9:"secret123";}';
$user = unserialize($serialized);
echo $user->name; // Иван
echo $user->email; // ivan@example.com
// Приватное свойство password также восстановлено, но напрямую недоступно
?>
Важно: При десериализации PHP пытается загрузить класс, если он ещё не определён. Если класс не существует, будет создан экземпляр встроенного класса __PHP_Incomplete_Class.
Магические методы __sleep() и __wakeup()
Для контроля над процессом сериализации PHP предоставляет два магических метода:
__sleep()— вызывается перед сериализацией. Должен вернуть массив имён свойств, которые нужно сериализовать. Удобен для закрытия соединений с БД, освобождения ресурсов или скрытия конфиденциальных данных.__wakeup()— вызывается сразу после десериализации. Используется для повторного подключения к БД, восстановления ресурсов или проверки целостности данных.
Пример с __sleep() и __wakeup()
<?php
class DatabaseConnection {
private $host;
private $user;
private $password;
private $connection;
public function __construct($host, $user, $password) {
$this->host = $host;
$this->user = $user;
$this->password = $password;
$this->connect();
}
private function connect() {
// Эмуляция подключения
$this->connection = "Ресурс подключения к {$this->host}";
}
public function __sleep() {
// Не сериализуем ресурс соединения, только данные для повторного подключения
return ['host', 'user', 'password'];
}
public function __wakeup() {
// Восстанавливаем соединение после десериализации
$this->connect();
}
public function getConnection() {
return $this->connection;
}
}
$db = new DatabaseConnection('localhost', 'root', 'pass');
$serialized = serialize($db);
$restoredDb = unserialize($serialized);
echo $restoredDb->getConnection(); // Ресурс подключения к localhost
?>
Без __sleep() попытка сериализовать объект с ресурсом (например, дескриптором фай