Ответ 1
Как уже описано, __sleep()
вызывается, когда вы serialize()
объект и __wakeup()
после unserialize()
it.
Сериализация используется для сохранения объектов: вы получите представление объекта в виде строки, которая затем может быть сохранена в $_SESSION
, базе данных, файлах cookie или в любом другом месте, которое вы хотите.
Значения ресурсов
Однако serialize()
не может сериализовать (т.е. преобразовать в текстовое представление) значение с помощью типа ресурса. Вот почему все эти значения исчезнут после unserialize()
.
График объектов
или членов, а также членов-членов и... ad infinitum
Другим, возможно, более важным является то, что serialize()
будет пересекать весь граф объекта $obj
, если вы его сериализуете. Это здорово, когда вам это нужно, но если вам нужны только части объекта, а определенные связанные объекты являются "специфичными для выполнения" и распределяются между множеством объектов, но и другими объектами, вы можете не хотеть этого поведения.
PHP правильно обрабатывает циклические графики! Значение: If (член) $ссылки на $b, а ссылки $b на $a обрабатываются правильно, но на многих уровнях.
Пример - объекты, специфичные для сеанса (общие)
Например, объект $database
ссылается на $obj->db
, но также на другие объекты. Вы хотите, чтобы $obj->db
были теми же объектами - после unserialize()
ing - все остальные объекты в следующем сеансе, а не изолированный экземпляр объекта базы данных.
В этом случае у вас будет метод __sleep()
, например:
/**
/* DB instance will be replaced with the one from the current session once unserialized()
*/
public function __sleep() {
unset($this->db);
}
а затем восстановить его следующим образом:
public function __wakeup() {
$this->db = <acquire this session db object>
}
Другая возможность заключается в том, что объект является частью некоторой (глобальной) структуры данных, где он должен быть зарегистрирован. Вы можете сделать это вручную, конечно:
$obj = unserialize($serialized_obj);
Thing::register($obj);
Однако, если это часть контракта с объектами, что он должен быть в этом реестре, не рекомендуется оставлять этот магический вызов пользователю вашего объекта. Идеальное решение заключается в том, что объект заботится об этом, то есть регистрируется в Thing
. То, что __wakeup()
позволяет вам прозрачно (т.е. Больше не беспокоиться об этой магической зависимости) для вашего клиента.
Аналогичным образом вы можете использовать __sleep()
для "деинсталляции" объекта, если это необходимо. (Объекты не уничтожаются, когда они сериализованы, но это может иметь смысл в вашем контексте.)
Затворы
И последнее, но не менее важное: закрытие делает не сериализацию поддержки. Это означает, что вам нужно будет воссоздать все прикрепленные закрытия в __wakeup()
.