Что такое использование методов __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); ?>