Exemples

Nous définissons trois classes, qui implémentent chacune une méthode de stockage différente :

Exemple #1 storage_classes.inc

<?php
class FileStorage {
   var $data;

   function FileStorage($data) 
   {
	   $this->data = $data;
   }

   function write($name) 
   {
	   $fp = fopen(name, "w");
	   fwrite($fp, $this->data);
	   fclose($data);
   }
}

class WDDXStorage {
   var $data;
   var $version = "1.0";
   var $_id; // variable "privée"

   function WDDXStorage($data) 
   {
	   $this->data = $data;
	   $this->_id = $this->_genID();
   }

   function store()
   {
	   if ($this->_id) {
		   $pid = wddx_packet_start($this->_id);
		   wddx_add_vars($pid, "this->data");
		   $packet = wddx_packet_end($pid);
	   } else {
		   $packet = wddx_serialize_value($this->data);
	   }
	   $dbh = dba_open("varstore", "w", "gdbm");
	   dba_insert(md5(uniqid("", true)), $packet, $dbh);
	   dba_close($dbh);
   }

   // méthode privée
   function _genID()
   {
	   return md5(uniqid(rand(), true));
   }
}

class DBStorage {
   var $data;
   var $dbtype = "mysql";

   function DBStorage($data) 
   {
	   $this->data = $data;
   }

   function save() 
   {
	   $dbh = mysql_connect();
	   mysql_select_db("storage", $dbh);
	   $serdata = serialize($this->data);
	   mysql_query("insert into vars ('$serdata',now())", $dbh);
	   mysql_close($dbh);
   }
}

?>

Puis, nous "instantions" quelques objets issus de ces classes, et nous réalisons des agrégations et désagrégations, tout en affichant quelques résultats :

Exemple #2 test_aggregation.php

<?php
include "storageclasses.inc";

// quelques utilitaires

function p_arr($arr) 
{
   foreach ($arr as $k => $v)
	   $out[] = "\t$k => $v";
   return implode("\n", $out);
}

function object_info($obj) 
{
   $out[] = "Classe : " . get_class($obj);
   foreach (get_object_vars($obj) as $var=>$val) {
	   if (is_array($val)) {
		   $out[] = "propriété : $var (array)\n" . p_arr($val);
	   } else {
		   $out[] = "propriété : $var = $val";
	   }
   }
   foreach (get_class_methods($obj) as $method) {
	   $out[] = "méthode : $method";
   }
   return implode("\n", $out);
}


$data = array(M_PI, "kludge != cruft");

// créons quelques objets simples
$fs = new FileStorage($data);
$ws = new WDDXStorage($data);

// affichons des informations sur ces objets
echo "\$fs object\n";
echo object_info($fs) . "\n";
echo "\n\$ws object\n";
echo object_info($ws) . "\n";

// maintenant, quelques agrégations

echo "\nagrégeons \$fs avec la classe WDDXStorage\n";
aggregate($fs, "WDDXStorage");
echo "L'objet \$fs \n";
echo object_info($fs) . "\n";

echo"\nagrégeons le résultat avec la classe DBStorage \n";
aggregate($fs, "DBStorage");
echo "L'objet \$fs \n";
echo object_info($fs)."\n";

echo "\nEt finalement, désagrégeons WDDXStorage\n";
deaggregate($fs, "WDDXStorage");
echo "L'objet \$fs \n";
echo object_info($fs) . "\n";

?>

Etudions maintenant le résultat du script pour comprendre les effets secondaires et les limitations des agrégations d'objets en PHP. D'abord, nous avons créé $fs et $ws et ils fournissent le bon résultat (suivant la définition de leur classe). Notez que dans le but de l'agrégation d'objets, les éléments privés d'une classe ou d'un objet doivent commencer par un souligné ("_"), même s'il n'y a pas de distinction réelle entre un objet privé et un objet public.

$fs object
Classe : filestorage
propriété : data (array)
   0 => 3.1415926535898
   1 => kludge != cruft
méthode : filestorage
méthode : write

$ws object
Classe : wddxstorage
propriété : data (array)
   0 => 3.1415926535898
   1 => kludge != cruft
propriété : version = 1.0
propriété: _id = ID::9bb2b640764d4370eb04808af8b076a5
méthode : wddxstorage
méthode : store
méthode : _genid

Nous agrégeons alors $fs avec la classe WDDXStorage, et nous affichons les informations. Nous pouvons aussi voir que même si l'objet $fs est toujours du type FileStorage, il a maintenant la propriété $version, et la méthode store(), qui sont définies dans WDDXStorage. Une chose importante à noter est que les éléments privés n'ont pas été agrégés, même s'ils sont présents dans l'objet $ws. Un autre absent est le constructeur de WDDXStorage, qu'il n'est pas logique d'agréger.

agrégeons \$fs avec la classe WDDXStorage
L'objet $fs
Classe : filestorage
propriété : data (array)
     0 => 3.1415926535898
     1 => kludge != cruft
propriété : version = 1.0
méthode : filestorage
méthode : write
méthode : store

Le processus d'agrégation est cumulatif, ce qui fait que lorsque nous agrégeons $fs avec la classe DBStorage, nous générons un objet qui peut utiliser n'importe laquelle des méthodes de stockage de ces classes.

agrégeons le résultat avec la classe DBStorage
L'objet $fs
Classe : filestorage
propriété : data (array)
     0 => 3.1415926535898
     1 => kludge != cruft
propriété : version = 1.0
propriété : dbtype = mysql
méthode : filestorage
méthode : write
méthode : store
méthode : save

Finalement, de la même façon que nous avons agrégé les méthodes et propriétés dynamiquement, nous pouvons aussi les désagréger. Si nous désagrégeons la classe WDDXStorage de l'objet $fs, nous allons obtenir :

Et finalement, désagrégeons WDDXStorage
L'objet $fs
Classe : filestorage
propriété : data (array)
     0 => 3.1415926535898
     1 => kludge != cruft
propriété : dbtype = mysql
méthode : filestorage
méthode : write
méthode : save

Un point que nous n'avons pas mentionné ci-dessus et que l'agrégation ne va pas écraser les méthodes ou propriétés déjà existantes dans l'objet principal. Par exemple, la classe FileStorage définit une propriété $data, et la classe WDDXStorage aussi. Mais cette dernière ne sera pas impliquée dans l'agrégation.

LoadingChargement en cours