Infos

Linéarisation avec __sleep et __wakeup

Nous allons voir comment fonctionne la linéarisation d'une class en PHP et le rôle des méthodes "magiques" __sleep et __wakeup.

1. Linéarisation, kézako ?

Linéariser un objet c'est le transformer en une chaîne de caractères. Celle-ci peut alors être stockée, comme n'importe quelle autre chaîne de caractères, dans un fichier, une base de données (...) ou transmise comme une variable à une autre page. L'objet initial est récupéré intact en soumettant cette chaîne à la fonction de délinéarisation.

  • serialize est la fonction de linéarisation, elle peut recevoir toute forme de variables et d'objets, à l'exception des objets internes (voir plus bas).
  • unserialize est la fonction de délinéarisation.

Mise en pratique

$volatiles = array('canard', 'pingouin', 'manchot', 'poulet');

$lin = serialize($volatiles);
// $lin contient maintenant le tableau $volatiles linéarisé
echo $lin;
// Affiche : a:4:{i:0;s:6:"canard";i:1;s:8:"pingouin";i:2;s:7:"manchot";i:3;s:6:"poulet";}

$de_lin = unserialize($lin);
// $de_lin est la version "délinéarisée" de $lin

if($volatiles === $de_lin){
    echo '$volatiles est bien égal à $de_lin !';
}

2. __sleep et __wakeup

Fonctionnement

Lors de la linéarisation d'une class, la méthode __sleep est automatiquement appelée si elle existe. Ca permet d'effectuer des opérations préalables avant le stockage de l'objet. __sleep doit retourner un tableau comportant le nom des variables de la class qui seront sauvegardées.
La méthode __wakeup est appelée par unserialize pour finir de rétablir l'objet.

Utilisation

La première fonction qui vient à l'esprit est d'utiliser __sleep pour stocker uniquement ce qui est nécessaire et d'utiliser __wakeup pour rétablir les connexions aux bases de données. Ceci est en effet un usage très fréquent.

Utilisation classique

class exemple{
    public $var1 = NULL, $var2 = 'Inutile';

    function __sleep(){
        return array('var1');
    }

    function __wakeup(){
        mysql_connect();
    }
}

$ex = new exemple();

$lin = serialize($ex);
// Comme $ex est une class, la methode __sleep est automatiquement appelée.
// __sleep retourne un tableau dans lequel sont listées les variables à sauvegarder

$de_lin = unserialize($lin);
// délinéarise $lin. Comme il s'agit d'une class, la méthode __wakeup est automatiquement appelée

Sur les objets internes

Serialize ne peut stoquer directement des objets internes, par exemple les objets DOM.

Ne fonctionne pas

class xmlExemple{
    function __construct($xml){
        $this->dom = DomDocument::loadXML($xml);
    }
    
    function printXml(){
     echo $this->dom->saveXML();
    }

    function __sleep(){
     return array('dom');
    }
}

$xmlExemple = new xmlExemple('Exemple');

$lin = serialize($xmlExemple);
$de_lin = unserialize($lin);
$de_lin->printXml(); // Ne marche pas ! L'objet DOM n'a pas été restauré.

La solution est ici toute simple, il suffit de sauvegarder le contenu de l'objet DOM en XML.

Utilise __sleep et __wakeup pour sauvegarder l'objet DOM

class xmlExemple{
    function __construct($xml){
        $this->dom = DomDocument::loadXML($xml);
    }

    function printXml(){
     echo $this->dom->saveXML();
    }

    function __sleep(){
     $this->xml = $this->dom->saveXML();
     return array('xml');
    }
    
    function __wakeup(){
        $this->__construct($this->xml);
    }
}

$xmlExemple = new xmlExemple('Exemple');

$lin = serialize($xmlExemple);
$de_lin = unserialize($lin);
$de_lin->printXml(); // fonctionne !

Ceci peut bien sûr s'adapter à de multiples situations.

La doc

La documentation officielle en français :

0.029' | CSS | XHTML 1.0 Strict
© 7px.net | Choisir un style : archycal | classic | cleersea