Menu
Coddy logo textTech

__serialize и __unserialize

Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy — урок 49 из 91.

Когда вам нужно преобразовать объект в строку для хранения или передачи, PHP использует сериализацию. Магические методы __serialize() и __unserialize() дают вам контроль над тем, какие именно данные сохраняются и как они восстанавливаются.

Метод __serialize() возвращает массив данных для сериализации, в то время как __unserialize() принимает этот массив и восстанавливает объект:

<?php
class Session {
    public function __construct(
        private string $userId,
        private array $data,
        private int $createdAt
    ) {}
    
    public function __serialize(): array {
        return [
            'userId' => $this->userId,
            'data' => $this->data
        ];
    }
    
    public function __unserialize(array $data): void {
        $this->userId = $data['userId'];
        $this->data = $data['data'];
        $this->createdAt = time();
    }
    
    public function getCreatedAt(): int {
        return $this->createdAt;
    }
}

$session = new Session("user123", ["theme" => "dark"], time());
$serialized = serialize($session);

$restored = unserialize($serialized);
echo "User: " . $restored->getCreatedAt();

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

Эти методы заменили старые методы __sleep() и __wakeup() в PHP 7.4, предлагая более чистый подход, при котором вы работаете напрямую с массивами данных вместо имен свойств.

challenge icon

Задание

Легко

Давайте создадим систему кэширования профилей пользователей, которая демонстрирует, как __serialize() и __unserialize() дают вам контроль над тем, какие данные сохраняются и как они восстанавливаются.

Вы организуете свой код в двух файлах:

  • UserProfile.php — Создайте класс UserProfile, который представляет профиль пользователя с возможностями кэширования. Используйте продвижение параметров конструктора (constructor promotion) для определения приватных свойств $userId (string), $username (string), $email (string) и $accessToken (string). Добавьте приватное свойство $cachedAt, которое хранит время кэширования профиля (изначально установите его в значение "not cached" в конструкторе). Вашему классу необходимы:
    • __serialize() — Возвращает массив, содержащий только userId, username и email. accessToken является конфиденциальным и никогда не должен сериализоваться. Метка времени cachedAt будет регенерирована при восстановлении.
    • __unserialize() — Восстанавливает userId, username и email из массива данных. Устанавливает accessToken в значение "expired" (так как токены не должны сохраняться).
    • getInfo() — Возвращает строку в формате: "[username] ([email]) - Token: [accessToken] - Cached: [cachedAt]"
  • main.php — Подключите файл UserProfile. Вы получите четыре входных значения: ID пользователя, имя пользователя, email и токен доступа. Создайте экземпляр UserProfile с этими значениями. Выведите три строки:
    • Информацию об оригинальном профиле (до сериализации)
    • Сериализуйте профиль с помощью serialize(), затем десериализуйте его с помощью unserialize(), чтобы создать восстановленный профиль. Выведите информацию о восстановленном профиле.
    • Выведите "Token preserved: yes" или "Token preserved: no" в зависимости от того, совпадает ли токен восстановленного профиля с оригинальным (подсказка: он не должен совпадать, так как токены истекают при восстановлении)

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

Шпаргалка

Магические методы __serialize() и __unserialize() управляют тем, какие данные сохраняются во время сериализации и как объекты восстанавливаются.

__serialize() возвращает массив данных для сериализации:

<?php
public function __serialize(): array {
    return [
        'userId' => $this->userId,
        'data' => $this->data
    ];
}

__unserialize() получает массив и пересобирает объект:

<?php
public function __unserialize(array $data): void {
    $this->userId = $data['userId'];
    $this->data = $data['data'];
    $this->createdAt = time();
}

Используйте serialize() для преобразования объекта в строку и unserialize() для его восстановления:

<?php
$serialized = serialize($session);
$restored = unserialize($serialized);

Эти методы полезны для исключения конфиденциальных данных, временных значений или ресурсов, которые не могут быть сериализованы (например, соединений с базой данных). Свойства могут быть регенерированы с новыми значениями во время десериализации.

Попробуйте сами

<?php

require_once 'UserProfile.php';

// Чтение входных данных
$userId = trim(fgets(STDIN));
$username = trim(fgets(STDIN));
$email = trim(fgets(STDIN));
$accessToken = trim(fgets(STDIN));

// TODO: Создать экземпляр UserProfile с входными значениями

// TODO: Вывести информацию об исходном профиле (до сериализации)

// TODO: Сериализовать профиль, затем десериализовать его для создания восстановленного профиля

// TODO: Вывести информацию о восстановленном профиле

// TODO: Вывести "Token preserved: yes" или "Token preserved: no"
// в зависимости от того, совпадает ли токен восстановленного профиля с оригиналом

?>
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование