Использование магических методов PHP __sleep и __wakeup

Что такое использование методов __sleep и __wakeup magic в PHP? Я прочитал документацию по PHP, но до сих пор неясно:

 class sleepWakeup { public function __construct() { // constructor // } public function __sleep() { echo 'Time to sleep.'; } public function __wakeup() { echo 'Time to wakeup.'; } } $ob = new sleepWakeup(); // call __sleep method echo $ob->__sleep(); echo "\n"; // call __wakeup method echo $ob->__wakeup(); 

Этот пример кода печатает:

 Time to sleep. Time to wakeup. 

Если бы я переименовал __sleep и __wakeup в foo и bar то он сделает то же самое. Каково надлежащее использование этих двух методов?

Solutions Collecting From Web of "Использование магических методов PHP __sleep и __wakeup"

Как уже описано, __sleep() вызывается, когда вы serialize() объект и __wakeup() после того, как вы unserialize() его.

Сериализация используется для сохранения объектов: вы получите представление объекта в виде строки, которая затем может быть сохранена в $_SESSION , базе данных, кукисах или в любом другом месте, которое вы хотите.

Значения ресурсов

Однако serialize() не может сериализовать (т. Е. Преобразовать в текстовое представление) значение sof типа ресурса . Вот почему все эти значения unserialize() после unserialize() .

График объектов

или членов, и членов членов, и … ad infinitum

Другой, возможно, более важный момент в том, что serialize() будет пересекать весь граф объектов $obj если вы его сериализуете. Это здорово, когда вам это нужно, но если вам нужны только части объекта, а определенные связанные объекты «зависят от времени выполнения» и распределяются между множеством объектов, но и другими объектами, вы можете не хотеть этого поведения.

PHP правильно обрабатывает циклические графики! Значение: Если (член) $ ссылки на $ 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); } с /** /* 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's db object> } 

Другая возможность заключается в том, что объект является частью некоторой (глобальной) структуры данных, где ее необходимо зарегистрировать. Конечно, вы можете сделать это вручную:

 $obj = unserialize($serialized_obj); Thing::register($obj); 

Однако, если это часть контракта с объектами, что он должен быть в этом реестре, не рекомендуется оставлять этот магический вызов пользователю вашего объекта. Идеальное решение, если объект заботится о своих обязанностях, т.е. регистрируется в Thing . Это то, что __wakeup() позволяет вам делать прозрачно (т. __wakeup() Больше не беспокоится об этой магической зависимости) для вашего клиента.

Аналогичным образом вы можете использовать __sleep() для « __sleep() » объекта, если это необходимо. (Объекты не уничтожаются, когда они сериализованы, но это может иметь смысл в вашем контексте.)

Затворы

И последнее, но не менее важное: закрытие также не поддерживает сериализацию. Это означает, что вам нужно будет воссоздать все прикрепленные закрытия в __wakeup() .

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

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

  class demoSleepWakeup { public $resourceM; public $arrayM; public function __construct() { $this->resourceM = fopen("demo.txt","w"); $this->arrayM = array(1,2,3,4);`enter code here` } public function __sleep(){ return array('arrayM'); } public function __wakeup(){ $this->resourceM = fopen("demo.txt","w"); } } $obj = new demoSleepWakeup(); $serializedStr = serialize($obj); var_dump($obj); var_dump($serializedStr); var_dump(unserialize($serializedStr)); 

Сценарий 1:
Сначала, комментируя метод __sleep () и __wakeup (), проверьте вывод. Вы обнаружите, что ресурс отсутствует, когда вы несериализуете его.

Сценарий 2:
Теперь попробуйте запустить его, раскомментируя их, вы поймете, что объект, сбрасываемый в первом и последнем var_dump, будет таким же.

попробуйте это

 <?php $ob = new sleepWakeup(); $safe_me = serialize($ob); $ob = unserialze($safe_me); ?>