Metody __sleep() i __wakeup() należą do metod magicznych dostępnych w PHP.
Metody magiczne są uruchamiane przez wykonanie na obiekcie określonych czynności. __sleep i __wakeup są powiązane odpowiednio z serializowaniem i deserializowaniem obiektów (wbudowane funkcje PHP serialize() i unserialize()).
Metoda magiczna __sleep() wywoływana jest w momencie serializowania obiektu metodą serialize(). __sleep powinna zwracać tablicę zawierającą nazwy atrybutów które mają zostać zserializowane. Takie określenie, które trybuty serializowanego obiektu mają być zserializowane, jest pomocne przy serializacji dużych obiektów, gdy nie chcemy aby wszystkie atrybuty obiektu zostały zserializowane.
Natomiast metoda magiczna __wakeup() jest uruchamiana przy próbie deserializacji obiektu metodą unserialize(). __wakeup() przeznaczona jest do wykonania dodatkowych akcji podczas deserializacji. Może to być na przykład próba odtworzenia stanu klasy sprzed serializacji na podstawie wartości które zostały zserializowane. Mogą to być działania które zostały wykonane w konstruktorze klasy, a które nie są wykonane przy deserializacji (przy deserializacji nie jest uruchamiana metoda __construct()); Ogólnie można powiedzieć że metoda __wakeup() jest tym dla obiektu przy deserializacji, czym jest metoda __construct() przy tworzeniu obiektu.
Sposób działania tej metody zostanie przedstawiona na podstawie obiektu Person, który zawiera atrybuty name, surname, birthDate oraz age. Przy czym zakładamy że w zserializowanej postaci nie jest potrzebny atrybut Age ponieważ wartość tą można obliczyć przy pomocy wartości atrybutu brithDate. Aby pominąć ten atrybut, należy w metodzie magicznej __sleep() podać wszystkie atrybuty z wyjątkiem atrybutu.
Jednak zauważ że przy deserializacji w w obiekcie, atrybut age będzie pusty. Z pomocą przychodzi tutaj jednak metoda magiczna __wakeup(). W jej ciele obliczamy wartość age i przypisujemy ją do tego atrybutu.
Opisywany tutaj przykład jest poniżej:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
<?php class Person { /** @var string */ private $name; /** @var string */ private $surname; /** @var DateTime */ private $birthDate; /** @var int */ private $age; /** * @param string $name * @param string $surname * @param DateTime $birthDate */ public function __construct(string $name, string $surname, \DateTime $birthDate) { $this->name = $name; $this->surname = $surname; $this->birthDate = $birthDate; $this->age = $this->calculateAge($birthDate); } /** * @param DateTime $birthDate * @return int */ protected function calculateAge(\DateTime $birthDate): int { $now = new \DateTime(); $interval = $now->diff($birthDate); return $interval->y; } public function __sleep() { return ['name', 'surname', 'birthDate']; } public function __wakeup() { $this->age = $this->calculateAge($this->birthDate); } } $tom = new Person('Tomasz', 'Kowalski', new \DateTime('1985-11-01')); echo 'Tom:' . PHP_EOL; var_dump($tom); $serializedPerson = serialize($tom); echo PHP_EOL . 'Serialized Tom:' . PHP_EOL; echo $serializedPerson . PHP_EOL; echo PHP_EOL . 'Unserialized Tom:' . PHP_EOL; var_dump(unserialize($serializedPerson)); |
Rezultat skryptu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
object(Person)[1] private 'name' => string 'Tomasz' (length=6) private 'surname' => string 'Kowalski' (length=8) private 'birthDate' => object(DateTime)[2] public 'date' => string '1985-11-01 00:00:00.000000' (length=26) public 'timezone_type' => int 3 public 'timezone' => string 'Europe/Berlin' (length=13) private 'age' => int 33 Serialized Tom: O:6:"Person":3:{s:12:"Personname";s:6:"Tomasz";s:15:"Personsurname";s:8:"Kowalski";s:17:"PersonbirthDate";O:8:"DateTime":3:{s:4:"date";s:26:"1985-11-01 00:00:00.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:13:"Europe/Berlin";}} Unserialized Tom: object(Person)[4] private 'name' => string 'Tomasz' (length=6) private 'surname' => string 'Kowalski' (length=8) private 'birthDate' => object(DateTime)[3] public 'date' => string '1985-11-01 00:00:00.000000' (length=26) public 'timezone_type' => int 3 public 'timezone' => string 'Europe/Berlin' (length=13) private 'age' => int 33 |