Подтвердить что ты не робот

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

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

4b9b3361

Ответ 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().

Ответ 2

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

Ответ 3

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

    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, будет таким же.

Ответ 4

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

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