Korzystanie z magicznych metod PHP sen i przebudzenie

Jaki jest użytek z metod magicznych __sleep i __wakeup w PHP? Przeczytałem dokumentację PHP, ale nadal nie jest jasne:

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();

Ten przykładowy kod drukuje:

Time to sleep.
Time to wakeup.

Gdybym miał zmienić nazwę __sleep i __wakeup na foo i bar wtedy robi to samo. Jakie jest właściwe wykorzystanie tych dwóch metod?

Author: Chris Bornhoft, 2012-07-24

4 answers

Jak już opisano, __sleep() jest wywoływany, gdy ty serialize() obiekt i __wakeup() po tobie unserialize() to.

Serializacja jest używana do utrzymywania obiektów: otrzymasz reprezentację obiektu jako ciąg znaków, który może być następnie przechowywany w $_SESSION, bazie danych, ciasteczkach lub gdziekolwiek indziej.

Wartości zasobów

Jednakże, serialize() nie można serializować (tzn. przekształcić w reprezentację tekstową) wartości sof typ zasobu . Dlatego wszystkie te wartości znikną po unserialize() ING it.

Wykres obiektu

Lub członków, a członkowie członka i.. ad infinitum

Innym, być może ważniejszym punktem jest to, że serialize() przemierzy cały wykres obiektu $obj, jeśli go serializujesz. Jest to świetne, gdy jest to potrzebne, ale jeśli potrzebujesz tylko części obiektu, a niektóre połączone obiekty są "specyficzne dla środowiska uruchomieniowego" i współdzielone między wieloma obiektami, ale także przez inne obiekty, możesz nie chcieć tego zachowania.

PHP poprawnie obsługuje cykliczne wykresy! Znaczenie: If (a member of) $ a links to $b, and $b links to $a jest obsługiwane poprawnie niezależnie od głębokości wielu poziomów.

Przykład-obiekty specyficzne dla sesji (współdzielone)

Na przykład, obiekt $database jest odwoływany przez $obj->db, ale także przez inne obiekty. Będziesz chciał, aby $obj->db były tymi samymi obiektami - po unserialize()ing - które mają wszystkie inne obiekty w następnej sesji, a nie odizolowane instancja obiektu bazy danych.

W tym przypadku, masz __sleep() metodę taką jak ta:

/**
/* DB instance will be replaced with the one from the current session once unserialized()
 */
public function __sleep() {
    unset($this->db);
}

A następnie przywrócić go w ten sposób:

public function __wakeup() {
    $this->db = <acquire this session's db object>
}

Inną możliwością jest, że obiekt jest częścią jakiejś (globalnej) struktury danych, gdzie musi być zarejestrowany. Można to oczywiście zrobić ręcznie:

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

Jednak, jeśli jest to część Umowy obiektów, które muszą być w tym rejestrze, nie jest dobrym pomysłem, aby pozostawić to magiczne wezwanie do użytkownika obiekt. Idealnym rozwiązaniem jest, jeśli obiekt dba o swoje obowiązki, czyli jest zarejestrowany w Thing. To właśnie __wakeup() pozwala Ci robić to w sposób przejrzysty (tzn. nie musi już martwić się o tę magiczną zależność) z twoim klientem.

Podobnie, możesz użyć __sleep() do" wyrejestrowania " obiektu, jeśli jest to właściwe. (Obiekty nie są niszczone podczas serializacji, ale może to mieć sens w Twoim kontekście.)

Zamknięcia

[[21]}Last but not least, closures do nie również obsługuje serializację. Oznacza to, że będziesz musiał odtworzyć wszystkie załączone zamknięcia w __wakeup().
 34
Author: phant0m,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-24 13:10:42

Te metody są używane podczas wywoływania serialize () i unserialize () na obiektach, aby upewnić się, że masz hook, aby usunąć niektóre właściwości, takie jak połączenia z bazą danych i ustawić je z powrotem podczas ładowania. Dzieje się tak między innymi podczas przechowywania obiektów w sesjach.

 7
Author: Louis-Philippe Huberdeau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-24 11:59:21

Są one podobne do funkcji hook, które możemy używać zgodnie z naszymi potrzebami. Wymyśliłem ten prosty przykład w czasie rzeczywistym. Teraz spróbuj wykonać ten kod w dwóch scenariuszach:

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));

Scenariusz 1:

Najpierw komentując metody __sleep() i __wakeup(), Sprawdź wyjście. Znajdziesz brakujący zasób, gdy go anulujesz.

Scenariusz 2:

Teraz spróbuj je uruchomić, przekonasz się, że obiekt wrzucony do pierwszej i ostatniej var_dump będzie to samo.

 7
Author: Mohammed Asad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-08 06:24:24

Wypróbuj to

<?php
  $ob = new sleepWakeup();
  $safe_me = serialize($ob);
  $ob = unserialize($safe_me);
?>
 3
Author: donald123,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-05 20:00:56