Articles
This document is also available in English
Il est bien connu que les sessions ne supportent pas les ressources. Si vous placez dans une session une connexion à MySQL, par exemple, elle reviendra sous la forme d'une chaîne, assez narquoise. En PHP 5, vous obtiendrez une erreur fatale, bien plus conforme avec l'incapacité de PHP de restaurer la ressource.
Le problème vient du fait que les sessions stockent les données sous forme de fichier, et doivent transformer les ressources en mémoire en une représentation sous forme de chaîne de caractère. Pour les nombres, les chaînes, les tableaux ou les objets, c'est simple. Mais pour les ressources, cela peut être très difficile, comme pour un objet PDF de PDFlib, ou voire même impossible, comme pour une socket ou une connexion à un serveur SQL.
Cependant, tout espoir n'est pas perdu. En effet, s'il est impossible de sauver la ressource directement en session, il est possible de faire semblant. Pour cela, il suffit de créer deux méthodes magiques dans un objet : __sleep() et __wakeup().
__sleep() sera appelée automatiquement par PHP lors de la serialisation de l'objet. Cela va donner la possibilité au programme de ranger la ressource comme il le faut. Inversement, __wakeup() sera appelée lors de l'ouverture de la session, et donne une chance de rétablir la ressource dans son état initial.
Prenons un exemple. Créons un objet de connexion MySQL : cet exemple est simplifié pour être aussi clair que possible.
<?php class maDB { function __construct() { $this->res = mysqli_connect('localhost','user','pass','base'); } function __sleep() { mysqli_close($this->res); return array(); } function __wakeup() { $this->__construct(); } } $maBase = new maDB(); $x = serialize($maBase); $y = unserialize($x); >
Notez ici deux choses : nous avons introduit ces fonctions comme étant liées aux sessions. En fait, elles sont techniquement liées à serialize() et unserialize(), qui sont appelées par les sessions. Donc, il est possible d'utiliser ces fonctions magiques hors du contexte des fonctions.
Ensuite, __sleep() doit retourner un tableau contenant la liste des membres de maDB qui doivent être sauvés. Tous les autres seront ignorés. Si __sleep() ne retourne rien, alors l'objet sera entièrement perdu.
Que faire avec __sleep() et __wake() ?
L'exemple ci-dessus montre comment conserver une connexion ouverte entre deux sollications de scripts. Maintenant, il est possible de ranger sa connexion à MySQL dans la session, et ne plus s'en soucier : elle reviendra automatiquement.
Mais voici quelques autres applications de ces fonctions.
Protéger les données de sessions en les chiffrant
<?php class maClasse { function __construct() { $this->clair = 'php'; } function __sleep() { $this->chiffre = str_rot13($this->clair); return array('chiffre'); } function __wakeup() { $this->clair = str_rot13($this->chiffre); unset($this->chiffre); } } $maClasse = new maClasse(); print $x = serialize($maClasse); $y = unserialize($x); >
Note : utilisez un algorithme plus robuste que rot13, et un nom de membre un peu moins voyant que chiffré.
Protéger les données de sessions en les signant
<?php class maClasse { function __construct() { $this->a = 'b'; $this->c = 'd'; } function __sleep() { $membres = get_object_vars($this); $this->signature = md5('S3l'.join('|', array_values($membres))); $sauve = array_keys($membres); $sauve[] = 'signature'; return $sauve; } function __wakeup() { $membres = get_object_vars($this); $signature = $membres['signature']; unset($membres['signature']); $test = md5('S3l'.join('|', array_values($membres))); if ($test != $signature) { print "Attention, les données ont été modifiées"; } } } $maClasse = new maClasse(); print $x = serialize($maClasse); $y = unserialize($x); ??> gt;
Réduire la taille des données
Utilisez les fonctions de compression intégrées à PHP, comme gzip, bzip2 ou zip, pour réduire la taille des données qui seront stockées sur le disque. Moins de données représente souvent plus de rapidité.
<?php class maClasse { function __construct() { $this->a = str_repeat('abc', 1000); $this->premiers = array(2,3,5,7,11,13,17,19); } function __sleep() { $membres = get_object_vars($this); $this->compresse = bzcompress(serialize($membres)); return array('compresse'); } function __wakeup() { $membres = unserialize(bzdecompress($this->compresse)); unset($this->compresse); foreach($membres as $nom => $valeur) { $this->$nom = $valeur; } $this->premiers = array(2,3,5,7,11,13,17,19); } } $maClasse = new maClasse(); $x = serialize($maClasse); $y = unserialize($x); >
Vous pouvez aussi voir si vous ne pourriez pas recalculer les données d'une autre manière. Par exemple, ci-dessus, nous avons supprimé les nombres premiers qui sont faciles à recalculer, voire même qui apparaissent sous forme de constantes.
A mémoriser
- Les méthodes qui commencent par __ sont des méthodes magiques de PHP. Elles sont beaucoup plus nombreuses en PHP 5 qu'en PHP 4, mais __sleep() et __wakeup() fonctionnent déjà en PHP 4
- __sleep() et __wakeup() sont surtout destinées à faire le ménage et préparer les données pour le stockage. Ne vous lancez pas dans de grands chambardements, ce n'est pas l'endroit.
- ces fonctions sont distinctes du gestionnaire de sessions, mais fonctionnent bien avec lui.
- N'utilisez serialize() qu'avec des données qui restent sur le serveur. Ne vous en servez pas pour faire passer des structures complexes via le navigateur.
| < Précédent | Suivant > |
|---|
Vous devez vous connecter pour commenter


