Что такое использование методов __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 то он сделает то же самое. Каково надлежащее использование этих двух методов?
Как уже описано, __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); ?>