Menu
Coddy logo textTech

__serialize и __unserialize

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

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

Метод __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 "Created at: " . $restored->getCreatedAt();

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

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

challenge icon

Задание

Легко

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

Вы распределите код по двум файлам:

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

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

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

<?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: Print "Token preserved: yes" or "Token preserved: no"
// в зависимости от того, совпадает ли токен восстановленного профиля с оригинальным

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

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

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

Потренируйтесь самостоятельно: Онлайн-компилятор PHP