Сериализация объектов в PHP: функции, методы и практические примеры

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Сериализация объектов в 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() попытка сериализовать объект с ресурсом (например, дескриптором фай

Рекомендаций