#7.10 php ООП Упаковка и распаковка объекта (сериализация, десериализация). Перехват сериализации, методы __sleep() и __wakeup()

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

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

<?php
class Example
{
    private $property;

    public function __construct($property)
    {
        $this->property= $property;
    }

    public function get_property()
    {
        return $this->property;
    }
}
$obj = new Example(10);
$str= serialize($obj);
echo $str;

Полученная строка может быть, например, записана в файл или в базу данных для дальнейшего чтения и распаковки с помощью обратной функции unserialize:

$objFromString = unserialize($str);

При восстановлении объекта из строки с помощью unserialise будет создан объект, содержащий все public-, protected- и private-свойства упакованного ранее объекта. При этом, чтобы использовать его методы, например,

echo $objFromString->get_property(); 

скрипт, выполнивший распаковку, должен иметь доступ к описанию соответствующего класса (в нашем примере — это класс Example).

Перехват сериализации

Для управления процессом сериализации и десериализации объекта используются следующие специальные методы, которые должны быть описаны в классе:

  • __sleep — вызывается перед сериализацией объекта и возвращает список имен свойств, подлежащих сериализации. Все свойства объекта, не указанные в этом списке, будут проигнорированы при упаковке. Например,
    <?php
    class User
    {
        public $log; //логин пользователя
        public $pass; //пароль
    
        public function __construct($log, $pass)
        {
            $this->log= $log;
            $this->pass= $pass;
        }
    
        public function __sleep()
        {
            return ['log'];
        }
    }    
    
    $user = new User("Мария", "1234");
    $str = serialize($user);
    file_put_contents("file.txt",  $str);
    

    В результате выполнения примера будет создан файл file.txt, содержащий строку:

    O:4:"User":2:{s:4:"log";s:10:"Мария";}

    Как мы видим, свойство pass отсутствует в строке. Если файл существует, то его содержимое будет перезаписано. Подробнее работа с файлами рассмотрена в следующей главе.

  • __wakeup — выполняется после десереализации. Метод может выполнять какие-то дополнительные действия после распаковки, например, инициализировать динамические переменные объекта. Добавим метод __wakeup в класс User:
    <?php
    class User
    {
        public $log;
        public $pass;
    
        public function __construct($log, $pass)
        {
            $this->log= $log;
            $this->pass= $pass;
        }
    
        public function __sleep()
        {
            return ['log'];
        }
        
        public function __wakeup()
        {
           echo "Объект восстановлен.<BR>";
        }
    }    
    
    $str = file_get_contents("file.txt");
    $user = unserialize($str);
    

    Здесь для чтения строки из файла используется функция file_get_context, которая также будет подробнее рассмотрена в следующей главе. Метод __wakeup, добавленный в класс User, в данном случае просто выводит сообщение о распаковке объекта.