__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, предлагая более чистый подход, при котором вы работаете напрямую с массивами данных вместо имен свойств.
Задание
ЛегкоДавайте создадим систему кэширования профилей пользователей, которая демонстрирует, как __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"
// в зависимости от того, совпадает ли токен восстановленного профиля с оригиналом
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Итоги — Простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыИтоги — Иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateПодробный разбор модификаторов доступаГеттеры и сеттерыСокрытие данныхConstructor Promotion (8.0)Итоги — Система учета студентов10Продвинутые концепции ООП
Композиция против наследованияВнедрение зависимостейАнонимные классыПеречисления (PHP 8.1)Файберы (PHP 8.1)Глубокое погружение в клонирование объектовГенераторы и итераторы13Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий2Пространства имен и автозагрузка
Введение в пространства именКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerИтоги: структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс против абстрактного классаType Hinting с интерфейсамиИтоги — Калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeИтоги — Кастомная коллекция11Система типов и обработка ошибок
Объявление типовNullable-типыТипы объединения и пересеченияКлассы исключенийИерархия пользовательских исключенийTry, Catch, FinallyИтоги — Валидатор форм14Проект: Управление библиотекой
Обзор проектаКлассы Book и User3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищенные свойстваСвойства Readonly (PHP 8.1)Итоги — Менеджер банковского счета6Полиморфизм
Снова о переопределении методовПолиморфизм через интерфейсыType Hinting и Union TypesПозднее статическое связываниеИтоги — Payment Processor9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy