[php5] xml object serializer/unserializer

Soyez le premier à donner votre avis sur cette source.

Vue 10 671 fois - Téléchargée 505 fois

Description

Bon...je vais tenter d'expliquer le concept ;-)
Les adeptes de la POO PHP connaisse les fonctions serialize() et unserialize().
J'ai voulu, pour ma part, créer une classe générique permettant de linéariser un objet...en XML! Un peu comme XMLEncoder et XMLDecoder pour java.
Le but ? Obtenir des fichiers faciles à lire, voire à générer en php autrement qu'en créant un objet (cela peut servir de template), et contenant un objet déjà instancié.

Ce que fait cette classe : on lui passe un objet en paramètre. Elle récupère toutes les propriétés PUBLIQUES (j'y reviendrai) de cet objet, et créer une chaîne xml avec. Cette chaîne peut-être récupérée pour, par exemple, l'enregistrer dans un fichier.

Elle peut aussi, à partir d'une chaîne XML qu'elle a créée, qu'on lui passe en paramètre ou qu'elle va chercher dans ses propriétés, recréer une instance de cet objet.

Dans l'ordre, pour l'utilisation :
- on a besoin d'une instance d'une classe dont toutes les propriétés sont publiques. On modifie les propriétés etc...
- on instancie xmlSerialize :
$oxml = new xmlserialize ($oObj);
- on récupère les propriétés de l'objet :
$oxml -> getProps ();
- on sérialize l'objet :
$sXml = $oxml -> xmlToVars ();
- on fait ce qu'on veut avec $sXml...

Pour le unserialize : on lit le fichier dans lequel on a stocké le xml et on le met dans une chaine : $sXml par exemple, puis :
$newObjet = $oxml -> varsToXml ($sXml);

Et voilà :-)

Source / Exemple :


<?php
/**

  • CLASS xmlSerializer
  • object to xml serialization and unserialization
  • @auteur : johan <barbier_johan@hotmail.com>
  • @version : 1
  • @date : 2006/03/22
*
  • free to use, modify, please just tell me if you make any changes :-)
  • /
class xmlserialize { /**
  • private object oObj
  • the object we work on
  • /
private $oObj = null; /**
  • private array of object oPropObj
  • objects needed by the main object, because some of its properties are objects
  • /
private $oPropObj = array (); /**
  • private array aProps
  • the PUBLIC properties of the object
  • /
private $aProps = array (); /**
  • private string xml
  • the xml serailization of the object
  • /
private $xml = ''; /**
  • public string node
  • a fragment of the xml string
  • /
public $node = ''; /**
  • public function __construct
  • constructor
  • @Param (object) $obj : the object we want to serialize/unserialize
  • @Param (array) $oPropObj : array of objects needed by the main object
  • /
public function __construct ($obj, array $oPropObj = array ()) { if (!is_object ($obj)) { trigger_error ('The first argument given is not an object', E_USER_ERROR); } else { $this -> oObj = $obj; } if (!empty ($oPropObj)) { foreach ($oPropObj as $clef => $oVal) { if (is_object ($oVal)) { $this -> oPropObj[$clef]['object'] = $oVal; $this -> oPropObj[$clef]['class'] = get_class ($oVal); } } } } /**
  • public function getProps ()
  • method used to get the public properties of the object
  • /
public function getProps () { $this -> aProps = get_object_vars ($this -> oObj); } /**
  • private function recVarsToXml
  • method used to serialize the object, recursive
  • @Params (DomDocument) & docXml : the DomDocument object
  • @Params (DomElement) & xml : the current DomElement object
  • @Params (array) & aProps : the array of properties we work on recursively
  • /
private function recVarsToXml (& $docXml, & $xml, & $aProps) { foreach ($aProps as $clef => $val) { if (empty ($clef) || is_numeric ($clef)) { $clef = '_'.$clef; } $domClef = $docXml -> createElement ((string)$clef); $domClef = $xml -> appendChild ($domClef); if (is_scalar ($val)) { $valClef = $docXml -> createTextNode ((string)$val); $valClef = $domClef -> appendChild ($valClef); } else { if (is_array ($val)) { $this -> recVarsToXml ($docXml, $domClef, $val); } if (is_object ($val)) { $oXmlSerialize = new self ($val); $oXmlSerialize -> getProps (); $oXmlSerialize -> varsToXml (); $objClef = $docXml -> importNode ($oXmlSerialize -> node, true); $objClef = $domClef -> appendChild ($objClef); } } } } /**
  • public function varsToXml
  • method used to serialize the object
  • @Return (string) $xml : the xml string of the serialized object
  • /
public function varsToXml () { $docXml = new DOMDocument ('1.0', 'utf-8'); $xml = $docXml -> createElement ('object_'.get_class ($this -> oObj)); $xml = $docXml -> appendChild ($xml); $this -> recVarsToXml ($docXml, $xml, $this -> aProps); $this -> node = $xml; return $this -> xml = $docXml -> saveXML (); } /**
  • private function recXmlToVars
  • method used to unserialize the object, recursive
  • @Param (array) aProps : the array we work on recursively
  • /
private function recXmlToVars ($aProps) { foreach ($aProps as $clef => $val) { $cpt = count ($val); if ($cpt > 0) { foreach ($val as $k => $v) { $cpt2 = count ($v); if ($cpt2 > 0) { if (substr ($k, 0, 7) === 'object_') { foreach ($this -> oPropObj as $kObj => $vObj) { if ($this -> oPropObj[$kObj]['class'] === substr ($k, 7)) { $oXmlSerializer = new self ($this -> oPropObj[$kObj]['object']); $oXmlSerializer -> getProps (); $sXml = $oXmlSerializer -> varsToXml (); $oXmlSerializer -> xmlToVars ($sXml); $this -> oObj -> {$clef}[substr ($k, 7)] = $oXmlSerializer -> getObj (); } } } else { $this -> recXmlToVars ($v); } } else { if ($k{0} === '_') { $k = substr ($k, 1, strlen($k) - 1); } $this -> oObj -> {$clef}[$k] = current ($v); } } } elseif (!empty ($val)) { $this -> oObj -> $clef = current ($val); } } } /**
  • public function xmlToVars
  • method used to unserialize the object
  • @Param (string) xml : optional xml string (an already serialized object)
  • /
public function xmlToVars ($xml = '') { if (empty ($xml)) { $xml = simplexml_load_string ($this -> xml); } else { $xml = simplexml_load_string ($xml); } $this -> recXmlToVars ($xml); } /**
  • public function getObj
  • method used to get the unserialized object
  • @Return (object) oObj : the unserialized object
  • /
public function getObj () { return $this -> oObj; } /**
  • public method __toString
  • displays either the generated xml, or the object's properties to be serialized if the xml has not yet been generated
  • This method requires the XSL extension to be set i
  • Special thanks to Erwy, developpez.com XML forum administrator, who debugged my XSL :-), and to Tiscars, who tried to help too!
  • @Returns (string) sString
  • /
public function __toString () { $sString = ''; if (isset ($this -> xml) && !empty ($this -> xml)) { if (class_exists ('XSLTProcessor')) { $sString = '<br /><br /><span style="background-color: #ffcc33;">XML DISPLAY</span><br />'; $sXsl = <<<XSL <?xml version ="1.0" encoding ="utf-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" extension-element-prefixes="php"> <xsl:output method="xml" indent="yes" encoding="utf-8" /> <xsl:namespace-alias stylesheet-prefix="php" result-prefix="xsl" /> <xsl:template match="/"> <ul> <xsl:apply-templates select="*"/> </ul> </xsl:template> <xsl:template match="*"> <li> <xsl:value-of select="local-name ()"/><xsl:apply-templates select="text()"/> <xsl:if test="*"><ul> <xsl:apply-templates select="*"/> </ul></xsl:if> </li> </xsl:template> <xsl:template match="text()"> <xsl:value-of select="concat('=>',.)"/> </xsl:template> </xsl:stylesheet> XSL; $xsl = new XSLTProcessor(); $xsl->importStyleSheet(DOMDocument::loadXML($sXsl)); $sString .= $xsl->transformToXML(DOMDocument::loadXML($this -> xml)); } else { $sString = '<br /><br /><span style="background-color: #ffcc33;">XSL EXTENSION NOT SET IN YOUR PHP.INI</span><br /><br />'; } } else { $sString = '<br /><br /><span style="background-color: #ffcc33;">OBJECT PROPERTIES DISPLAY</span><br /><br />'; $sString .= '<pre>'.var_export ($this -> aProps, true).'</pre>'; } return $sString; } } ?>

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Messages postés
10840
Date d'inscription
lundi 24 février 2003
Statut
Modérateur
Dernière intervention
2 mars 2010
21
SKAAR => désolé, je n'avais pas vu ce message!! Je viens de le voir...donc, je réponds :
je suis en php 5.1.4 je crois (enfin, la dernière).
Pour ce qui est des extensions, attention...je n'utilise pas DOMXML, mais DOM (la version php5). Ce qui est très différent. A mon avis tes problèmes viennent de là. Tu montres la librairie XML, que je n'utilise pas ici. Vérifie que DOM soit installée correctement.
Et effectivement, mon script ne fonctionne pas en PHP4.3.10 puisqu'il utilise la syntaxe PHP5 exclusivement (notamment côté POO).
Messages postés
18
Date d'inscription
jeudi 1 juillet 2004
Statut
Membre
Dernière intervention
21 avril 2006

Malalam > Quelle version de php et des librairie utilises tu ? J'ai perdu le numéro de la version de php avec lequel j'avais testé, et là ya plus rien qui marche :(
J'ai des méthodes qui n'existe pas (entres autres : DomDocument::load(), DomDocument::loadXML(), domxml_xslt*(), ...) Ce qui est génant pour adapté un XSLT au XML et afficher le tout.
J'ai essayé de aussi de passer par :

<?php

$xml = domxml_open_file('aze.xml');
$xsl = domxml_open_file('aze.xslt');

$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
?>
Qui a mon sens devrait reprendre l'exemple qui est là : http://www.php.net/manual/en/function.xsl-xsltprocessor-transform-to-doc.php#AEN200744 sans utilisé la méthode load(). Mais j'ai une erreur à la ligne 7 (importStyleSheet($xsl)) : 'Warning: Invalid Document in g:\SambaMod\www\aze.php on line 7'.

Je me suis aperçu également que certaine méthodes que tu utilisais était 'deprecated' : http://www.php.net/manual/en/ref.domxml.php#domxml.deprecated

Voici un extrait de mon phpinfo validant le bon chargement de mes librairies :

xml

XML Support => active
XML Namespace Support => active
libxml2 Version => 2.6.22

xsl

XSL => enabled
libxslt Version => 1.1.15
libxslt compiled against libxml Version => 2.6.22
EXSLT => enabled
libexslt Version => 0.8.12

Existe-t'il des nouveaux noms pour les méthodes ? est-ce que les docs sont à jour ? Est-ce que j'utilise une version de PHP trop 'beta' (PHP5.1.2 pour windows) ? Est-ce que c'est parceque j'utilise PHP en ligne de comande ? Tant de question que je me pose et qui n'aboutissent à rien :'(
Si tu as quelquechose qui pourrait m'éclairer (autre qu'une source lumineuse ;) ), je t'en remercie.

Cordialement,

Scar.

PS : Ton script ne fonctionne pas avec EasyPHP1.8 (PHP4.3.10)
Messages postés
10840
Date d'inscription
lundi 24 février 2003
Statut
Modérateur
Dernière intervention
2 mars 2010
21
Yep, merci encore Kankrelune :-)

Si t'as des idées d'améliorations, n'hésites pas :-)

Je pense sous peu (bien qu'en l'état il me suffise pour le moment, pour mon utilisation) ajouter la possibilité de linéariser aussi les propriétés protégées et privées (avec comme condition l'ajout dans la classe à linéariser d'un setter et d'un getter spéciaux, c'est le seul moyen viable). Et je dois aussi me pencher sur les constantes et les statiques...que je ne prends pas en compte, là.
Messages postés
1293
Date d'inscription
mardi 9 novembre 2004
Statut
Membre
Dernière intervention
21 mai 2015

" Merci kankrelune, c'est flatteur venant d'un codeur comme toi :-)"

Ah non... c'est toi qui me flatte là... je me débrouille certe mais ça s'arrête là... .. . ;o)

Bon et bien sérialiseur testé... et approuvé... .. . :oD

Je met 9 parce que bien que le code demande quelques améliorations il tourne bien en l'état et surtout l'idée est très bonne et mérite bien ça... .. . :o)

@ tchaOo°
Messages postés
10840
Date d'inscription
lundi 24 février 2003
Statut
Modérateur
Dernière intervention
2 mars 2010
21
De rien :-) En plus, t'as dû prendre la 2de version, qui elle, n'est plus buggée : l'affichage devrait toujours être ok.
Afficher les 20 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.