POO PHP5 : Standard Php Library (SPL)
Date de publication : 14/01/2008 , Date de mise à jour : 27/11/08
Par
Julien Pauli (Tutoriels, article et conférences PHP et developpement web) (Blog)
PHP5 possède un modèle objet 'non vide' : il est agrémenté de classes et d'interfaces internes, réunies dans ce qu'on appelle la SPL, ou Standard PHP Library.
Nous allons voir en quoi ils peuvent s'avérer très utiles dans des développements orientés objets en PHP, de plus en plus nécéssaires de nos jours, afin de maintenir une cohérence logique dans ses programmes.
I. Introduction
II. Dans le coeur de la SPL
II-A. Iterator
II-B. IteratorIterator
II-C. Countable
II-D. RecursiveIterator
II-E. LimitIterator
II-F. SeekableIterator
II-G. FilterIterator
II-H. RegexIterator
II-I. RecursiveDirectoryIterator
II-J. AppendIterator
II-K. ParentIterator
II-L. CachingIterator
II-M. SimpleXMLIterator
II-N. ArrayAccess
II-O. ArrayObject
II-P. SplObjectStorage
II-Q. Fonctions de la SPL
III. Conclusion
I. Introduction
La plus grande amélioration que PHP5 a apporté à sa sortie, a été un modèle objet complet, très semblable à celui de Java ou C#.
Mais les développeurs de PHP ont saisi cette occasion pour intégrer dans son coeur tout un ensemble de classes et d'interfaces (nativement écrites en C, donc).
 |
Intégrées, plus ou moins : la SPL est en réalité une extension PHP, mais qui est très souvent (pour ne pas dire tout le temps) compilée dans PHP, quelle qu'en soit la distribution (Win, packages Linux...), ce qui donne l'impression de la nativité de ses fonctionnalités.
La SPL rend beaucoup de services, et de plus en plus d'extensions PHP en sont dépendantes. Ainsi, à partir de PHP5.3, il ne sera plus possible de désactiver l'intégration de la SPL via la commande de compilation. Elle sera réellement "nativement" intégrée.
|
Outre une approche procédurale conservée, il est désormais possible avec PHP5 de développer des pages et des processus entièrement orientés objets. La SPL, ou Standard PHP Library, est un ensemble de classes disponibles, prêtes à être utilisées ou implémentées.
Nous allons faire un petit tour de quelques puissantes fonctionnalités offertes par la SPL, et nous allons voir comment certaines fonctions natives du langage PHP peuvent être impactées.
Comme les images seraient trop grandes pour être affichées ici,
je vous propose quelques diagrammes directement sur le site officiel, vous pouvez aussi
regarder par là
Le développeur principal de la SPL est Marcus Boerger, il est actif sur les Mailing Lists de PHP et participe aussi au développement du modèle objet de PHP5.
Bien qu'intégrée nativement à PHP, la SPL possède son petit site à part, que vous trouverez ici :
http://www.php.net/~helly/php/ext/spl/
La documentation principale de PHP est souvent peu précise à son sujet, mieux vaut donc se fier à cette doc.
Vous trouverez toutes sortes de diagrammes de classe sur ce site, ainsi que l'API. Personnellement j'utilise Zend Studio mais sa base d'autocomplétion n'est pas parfaite, car la SPL, comme PHP, bouge beaucoup. Elle s'étoffe, et s'améliore de version en version.
Qu'importe, nous n'allons pas la détailler complètement, car si je compte le nombre de classes :
| liste des classes de la SPL |
|
Il m'en retourne 43 (à la date de cet article). Attention, il prend en compte les classes d'Exception, la SPL possédant ses propres Exceptions dont certaines rappelleront un peu Java : OutOfRangeException par exemple.
De plus, cette fonction ne liste pas les interfaces, or elles demeurent importantes, listons-les :
 |
La SPL est en développement permanent. Mettre à jour sa version de PHP est donc aussi gage d'un meilleur support SPL. Si certains frameworks nécéssitent une version de PHP précise comme configuration minimale, c'est en partie à cause du manque de certains objets dans
certaines versions de PHP. PHP5.0 ne comptait que 13 classes dans la SPL !
|
| liste des interfaces de la SPL |
|
Une manière plus simple : le très connu phpinfo() renvoie aussi des informations sur la SPL actuellement compilée :
II. Dans le coeur de la SPL
La SPL comporte ainsi des classes, et des interfaces (surtout des interfaces).
Le plus grand atout qu'offre la SPL est l'itérateur, et il y en a de toutes sortes. Rappelons d'abord ce qu'est un itérateur : C'est un objet qui permet de parcourir tous les éléments contenus dans un autre objet, le plus souvent il s'agit d'un conteneur (tableau, objet, jeu de résultats, arbre, liste ...). Le conteneur doit alors fournir des méthodes à l'itérateur (en implémentant une interface) afin de lui permettre de le parcourir.
On peut assimiler les itérateurs à des curseurs, dans le cas des bases de données.
En réalité, PHP utilise lui-même les itérateurs, à chaque fois que vous faites un foreach(), ou un count().
La syntaxe PHP du foreach est :
<?php
foreach ($foo as $key=>$val)
{
echo "$key vaut $val";
}
|
En interne, il se passe (grossièrement) ceci :
<?php
$foo = $foo->getIterator();
$foo->rewind();
while ($foo->valid())
{
echo "$foo->key() vaut $foo->current()";
$iterator->next();
}
|
Pour un type PHP array, nous avons à disposition des fonctions d'itération : next(), prev(), key(), current()... qui en interne vont utiliser les processus d'itération.
foreach fonctionne sur les objets depuis PHP5, car ils implémentent tous, en interne, l'interfaceTraversable, ils sont traversables par un itérateur.
Si j'utilise un foreach sur un objet, je vais avoir la liste de ses attributs publics, et de leurs valeurs, respectivement placés en clé, et valeur :
<?php
class bar
{
private $var = 2 ;
public $foo = 8;
}
$bar = new bar;
foreach ($bar AS $k=>$v)
{
echo $k . " a la valeur ". $v;
}
|
Ceci est le comportement par défaut de PHP, l'itérateur récupère les noms des proriétés publiques en clé, et leur valeur en valeur.
II-A. Iterator
Maintenant je peux changer ce comportement, en implémentant l'interface Iterator; rappelez-vous de la syntaxe avec le while situé plus haut :
<?php
class MonArray implements Iterator
{
private $_tab = array();
private $_pas;
public function __construct(array $array, $pas = 1)
{
$this->_tab = $array;
$this->_pas = (int)$pas;
}
public function valid()
{
return array_key_exists(key($this->_tab),$this->_tab);
}
public function next()
{
for ($i=1; $i<=$this->_pas;$i++) {
next($this->_tab);
}
return $this;
}
public function rewind()
{
reset($this->_tab);
return $this;
}
public function key()
{
return key($this->_tab);
}
public function current()
{
return current($this->_tab);
}
}
|
J'ai crée une classe "par dessus" un tableau, et je vais pouvoir spécifier le pas d'avancée de l'itération, dans le constructeur. Notez qu'il arrive que je retourne $this, sur des méthodes ne demandant pas obligatoirement un return.
Si je le désire, je pourrai ainsi chainer mes méthodes
<?php
$tablo = range (0,10);
$mon_array = new MonArray($tablo, 2));
foreach($mon_array AS $v)
{
echo $v;
}
|
Ce script m'affiche une suite de chiffres pairs 0,2,4,6,8,10.
J'ai donc modifié le comportement de foreach, en lui demandant d'itérer les éléments avec un pas que je donne au constructeur de mon objet, dans mon exemple.
 |
Très important : Utiliser les itérateurs permet de décaler la logique de selection et de navigation dans les données, depuis la boucle foreach, vers l'intérieur de l'objet itéré.
En gros : dans une boucle foreach, je n'ai plus aucune logique de selection des données, le foreach me retourne directement toutes les données auxquelles je m'attends.
|
II-B. IteratorIterator

IteratorIterator
IteratorIterator est un itérateur générique simple permettant d'itérer sur un objet implémentant Traversable, et donc à fortiori Iterator, qui en hérite.
foreach réagit à tout ce qui est Traversable, et certains objets internes à PHP comme PDOStatement implémentent cette interface.
On peut donc itérer dessus avec un simple foreach, mais si on doit utiliser un itérateur de plus haut niveau (comme ceux dans cet article), il sera necéssaire de tranformer la
structure traversable, en une structure itérable. IteratorIterator existe dans ce but.
La différence entre Traversable et Iterator est difficile à saisir, elle se situe en interne, dans le ZendEngine.
 |
Il n'est pas possible d'un point de vue utilisateur, d'implémenter l'interface Traversable directement, vous devez utiliser au minimum Iterator
|
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test','logintest','passtest');
$stmt = $pdo->query("SELECT * FROM test");
$it = new IteratorIterator($stmt);
foreach ($it as $val) {
echo $val;
}
|
Ce code affiche tous les résultats de la requête SQL concernée, mais l'objet IteratorIterator n'est pas nécessaire ici.
Voyez la section concernant CachingIterator pour un exemple plus concrêt.
II-C. Countable
Vous pouvez de même implémenter Countable, seule la méthode count() devra être définie, et elle va guider le comportement de la fonction count() de PHP :
<?php
class MonArray implements Iterator, Countable
{
public function count()
{
return count($this->_tab);
}
}
|
Je retourne naturellement le nombre de valeurs dans mon tableau, mais par exemple pour un conteneur représentant un jeu de résultats de base de données, le calcul aurait pu être différent.
II-D. RecursiveIterator
Grâce à l'interface RecursiveIterator , je vais implémenter des méthodes qui vont permettre à l'itérateur d'itérer sur des éléments, de même nature, nichés les uns dans les autres. Le cas bateau représente un tableau, dans un tableau, dans un tableau ...
Il est très facile d'itérer toutes les valeurs d'un coup, il suffit d'implémenter l'interface RecursiveIterator, et d'utiliser l'objet d'itération RecursiveIteratorIterator adapté avec :
<?php
class MonArray implements RecursiveIterator
{
private $_tab = array();
private $_pas;
public function __construct(array $array, $pas = 1)
{
$this->_tab = $array;
$this->_pas = (int)$pas;
}
public function valid()
{
return array_key_exists(key($this->_tab),$this->_tab);
}
public function next()
{
for ($i=1; $i<=$this->_pas;$i++) {
next($this->_tab);
}
return $this;
}
public function rewind()
{
reset($this->_tab);
return $this;
}
public function key()
{
return key($this->_tab);
}
public function current()
{
return current($this->_tab);
}
public function hasChildren()
{
return is_array(current($this->_tab));
}
public function getChildren()
{
return new self(current($this->_tab));
}
|
L'exemple :
<?php
$tablo = range (0,10);
$tablo[] = array('u',array('w'));
$tablo[] = array('x',array('z'));
$a = new RecursiveIteratorIterator(new MonArray($tablo,1));
foreach($a as $k=>$v)
{
echo $v.' ';
}
|
Affiche : 0 1 2 3 4 5 6 7 8 9 10 u w x z
RecursiveIteratorIterator est un itérateur, et il attend obligatoirement un paramètre implémentant l'interface RecursiveIterator. C'est le cas de MonArray. Il définit 2 nouvelles méthodes (par rapport à Iterator) qui vont être appelées par RecursiveIteratorIterator.
La première, hasChildren(), permet de savoir si le contenu en cours d'itération peut lui-même être itéré de la même manière que son père actuel. Savoir si le père possède un enfant.
On retourne donc un booléen qui dans notre cas regarde si l'élément couramment itéré est un autre tableau.
Si true est retourné, alors RecursiveIteratorIterator appelle immédiatement getChildren(), qui doit lui retourner un objet de la même classe que l'objet courament itéré (un enfant) à son tour, et il commence l'itération dessus.
Lorsqu'il a fini avec un enfant, il reprend le cours d'itération de son père, et ainsi de suite, quelle que soit la profondeur.
Nul besoin d'écrire des foreach dans des foreach..., la récursivité est assurée en interne par l'interface.
Vous pouvez créer de la même manière un menu de type 'fil conducteur' , contenant des élements de menus, ou des menus, etc.
De manière plus générale, tout élément composite, c'est à dire pouvant contenir des instances de lui-même, est susceptible d'implémenter RecursiveIterator.
On pense immédiatement au cas du dossier, comportant des dossiers, des fichiers, les fichiers étant des sortes de dossiers, etc. Nous allons traiter ce cas là.
II-E. LimitIterator
Cette classe est tout aussi simple, elle prend en paramètre un objet itérable (implémentant Iterator), puis une valeur de départ et une de fin.
Elle limite alors l'itérateur à certains résultats, tout bêtement, mais cela peut s'avérer plus que pratique :
Je vais afficher 8 9 10 u. Je pars du 5ème élément, et j'en affiche 4.
Il est à ce titre impressionnant de remarquer combien les gens essayent de réinventer la roue, en mettant des "if(...) return" ou je ne sais quoi dans leur boucle foreach, la rendant rapidement illisible.
II-F. SeekableIterator

SeekableIterator
SeekableIterator est un itérateur, mais dans lequel on peut se déplacer pour demander l'accès à l'enregistrement se trouvant à la position X.
<?php
class MonArray implements SeekableIterator
{
public function seek($index)
{
if (array_key_exists($index,$this->_tab)) {
$this->_key = $index;
return $this->_tab[$index];
}
}
}
|
On voit dans ce code que l'on peut déplacer le curseur de l'itérateur à la place que l'on souhaite.
II-G. FilterIterator
Même principe que LimitIterator, FilterIterator ne va retourner un résultat que si celui-ci est accepté, via une règle, que vous devez définir grâce à la méthode accept()
FilterIterator est une classe abstraite qui définit une méthode abstraite accept(). C'est un proxy qui agrège un itérateur, et va lui faire suivre les demandes.
<?php
class MonArrayFiltre extends FilterIterator
{
public function __construct(MonArray $mon_array)
{
parent::__construct(new RecursiveIteratorIterator($mon_array));
}
public function accept()
{
$it = $this->getInnerIterator();
return strlen($it->current()) == 1 ? true: false;
}
}
$a = new MonArrayFiltre(new MonArray(array('erf',array('r'),'x','y','zz')));
foreach($a AS $v) {
echo $v;
}
|
Ce petit code va afficher 'rxy'. Je lui ai demandé de n'afficher que les éléments de MonArray d'une seule lettre.
FilterIterator attend en paramètre un objet implémentant Iterator, c'est le cas de MonArray que nous avons déja vu plus haut.
II-H. RegexIterator

RegexIterator
RegexIterator hérite de FilterIterator, et permet d'utiliser la méthode accept() avec une expression régulière.
<?php
class DefinedFunction extends RegexIterator
{
public function __construct($regex, $mode = 0, $flags = 0, $preg_flags = 0)
{
$phpFunctions = get_defined_functions();
parent::__construct(new ArrayIterator(array_shift($phpFunctions)), $regex, $mode, $flags, $preg_flags);
}
}
foreach (new DefinedFunction('/str/') as $key=>$val) {
echo $val;
}
|
Cet exemple affiche toutes les fonctions PHP qui comprennent la chaine 'str' dedans. Là encore : la logique de selection des données est décalées dans l'itérateur et non plus dans la boucle
foreach.
RegexIterator permet de définir certains paramètres pour piloter l'expression régulière. $mode par exemple, peut contenir RegexIterator::GET_MATCH, qui va alors retourner le tableau $matches
utilisé par preg_match() en dessous, ou encore RegexIterator::SPLIT, qui va ordonner d'utiliser preg_split() en dessous. $flags peut contenir RegexIterator::USE_KEY, à ce moment là l'expression régulière est utilisée sur les clés des données d'entrées, et non plus sur les valeurs.
$preg_flags peut avoir n'importe quelle valeur des constantes globales PHP PREG_*
II-I. RecursiveDirectoryIterator
Revenons à la récursivité : RecursiveDirectoryIterator est une classe (et non une interface), qui permet la récursivité sur le parcours d'un répertoire.
Cet exemple crée un arbre au format HTML basique, de tout le dossier voulu, récursivement. Les dossiers le composant sont mis en gras, et la méthode getDepth() de l'itérateur permet de renvoyer sous forme d'entier, la profondeur dans laquelle il se trouve actuellement.
En un mot : merveilleux.
Si vous ne passez pas l'option SELF_FIRST, alors les dossiers listés, ne seront pas retournés, ce sont les « têtes de noeud » et l'itérateur ne les renvoie pas par défaut.
Une fois de plus, la documentation nous en apprend beaucoup sur toutes ces petites options.
Aussi, $entry est un objet SPLFileInfo et tout un tas de méthodes lui sont attachées dont __toString(), qui renvoie getFilename(), qui elle, renvoie par défaut le chemin complet du fichier, nous avons modifié ce comportement pour obtenir juste le nom du fichier, grâce à une constante passée au constructeur : KEY_AS_FILENAME.
II-J. AppendIterator
AppendIterator sert à fusionner plusieurs itérateurs en un seul.

AppendIterator
<?php
$arr1 = new ArrayIterator(array(1,2,3));
$arr2 = new ArrayIterator(array(4,5,6));
$ai = new AppendIterator();
$ai->append($arr1);
$ai->append($arr2);
foreach ($ai as $value) {
echo $value;
}
|
Ici aussi, nul besoin de faire suivre 2 instructions foreach l'une derrière l'autre : la logique de selection des données est déplacée dans l'objet itéré.
II-K. ParentIterator
ParentIterator est capable de ne retourner que les éléments ayant un enfants, depuis un RecursiveIterator quelconque.
Prennons un exemple avec un RecursiveArrayIterator :
<?php
$arr = array(
10,
array(1, 2, 3),
11,
array(4, 5, 6),
12 );
$pi = new ParentIterator(new RecursiveArrayIterator($arr));
foreach ($pi as $key=>$val) {
printf("%s - %s",$key,print_r($val,true));
}
|
II-L. CachingIterator
Qui n'a jamais souhaité répondre à cette question simple : Je suis dans un itérateur à une position X, "reste-t-il un élément après ma position, ou suis-je le dernier ?" ?
CachingIterator sert à répondre à cette question, il prend en paramètre un itérateur, et va le parcourir tout de suite, d'un coup.
En bouclant après sur le CachingIterator, on pourra alors savoir s'il reste des résultats, grâce à la méthode hasNext(), car celui-ci aura déja fait le tour de tous les éléments de la structure.
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test','logintest','passtest');
$stmt = new CachingIterator(new IteratorIterator($pdo->query("SELECT * FROM test")));
$stmt->rewind();
$stmt->next();
$stmt->next();
if ($stmt->hasNext()) {
echo "il reste des résultats";
}
|
Ici, un objet PDOStatement est utilisé (un jeu de résultats de base de données). Le CachingIterator permet de savoir s'il reste des résultats après avoir avancé 2 fois le pointeur interne.
II-M. SimpleXMLIterator
Cet objet est lié à simpleXML, et est automatiquement instancié lors de la création d'un noeud de SimpleXMLElements. Cependant, on peut l'instancier à part, en lui passant une chaine représentant
du XML valide.
Associé à un RecursiveIteratorIterator, on peut alors afficher le contenu de tous les noeuds facilement :

SimpleXMLIterator
Evidemment on peut le lier avec d'autres itérateurs.
II-N. ArrayAccess
L'interface ArrayAccess modifie carrément la manière dont se comportent les "[" et "]" pour accéder aux tableaux. Un objet peut alors être utilisé quasiment comme un tableau :
<?php
class functionProxy implements ArrayAccess
{
const SEPARATOR = '_';
private $_func;
public function offsetGet($offset)
{
$this->_func = $offset;
return $this;
}
public function offsetSet($offset,$value)
{
throw new Exception('Affectation interdite');
}
public function offsetExists($offset)
{
return ($this->_func == $offset);
}
public function offsetUnset($offset)
{
throw new Exception('Déréférencement interdit');
}
public function __call($func,$args)
{
$func = $this->_func.self::SEPARATOR.$func;
if (!function_exists($func)) {
throw new Exception("PHP function $func doesn't exist");
}
return @call_user_func_array($func,$args);
}
}
$p = new functionProxy();
$p['array']->combine($array1, $array2);
$p['str']->replace();
|
Si vous connaissez SimpleXML, vous noterez que vous pouvez accéder, via l'objet SimpleXMLElement, aux propriétés des tags xml, avec une syntaxe de tableau. Ca n'est pas magique ! ,
c'est que tout simplement SimpleXMLElement implémente ArrayAccess (en interne).
Ce comportement (comme tous les autres d'ailleurs) sont très utiles dans l'élaboration de frameworks.
II-O. ArrayObject
ArrayObject est sans doute l'objet le plus connu et le plus utile de la SPL. Pour faire simple : utilisez un tableau comme un objet.
Ou alors utilisez cet objet comme un tableau, complet (par défaut).
Vous pouvez aussi jouer avec son itérateur (interne), et le changer à votre guise.
<?php
$ar = new ArrayObject(array('a','b','c'));
$ar['key'] = 'd';
echo $ar->count();
$oldArray = $ar->exchangeArray(array(1,2,3));
foreach($ar as $value) {
echo $value;
}
|
En passant une constante spéciale au constructeur, on peut utiliser alors l'accès objet sur cet ArrayObject, en plus de l'accès tableau classique :
C'est pratique car quelques fois on se retrouve dans un cas ou l'analyseur syntaxique nous bloque, pensez à ceci :
$o->aMethod()['somekey'];
Si aMethod() retourne un array, on ne peut directement accéder à une propriété, sans passer par une valeur intermédiaire. Si on utilise l'ArrayObject correctement, alors on a
$o->aMethod()->somekey;
Ce qui est syntaxiquement valide.
Il est possible de même, de changer l'itérateur de l'arrayObject, par défaut, il s'agit d'un ArrayIterator, qui hérite entre autres de SeekableIterator (héritant d'Iterator).
On peut lui inculquer un RecursiveArrayIterator :
<?php
$ar = new ArrayObject(array('a','b','c',array('d')));
$ar['key'] = array('some value','another value');
$ar->setIteratorClass('RecursiveArrayIterator');
$itere = new RecursiveIteratorIterator($ar);
foreach($itere as $value) {
echo $value;
}
|
Définitivement terminés les foreach dans des foreach ^^
II-P. SplObjectStorage
SplObjectStorage est un conteneur d'objet itérable. Son avantage est qu'il s'occupe de stocker et de retrouver un objet, sans que l'on ait besoin de s'occuper de cela.
Lorsqu'un objet contient des instances d'autres objets, SplObjectStorage est l'endroit idéal pour les stocker. Plus simple qu'un tableau ou un ArrayObject, ce support de stockage s'occupe notament
d'éviter de stocker 2 mêmes instances, et leur suppression est très simple :

splobjectstorage
<?php
class Panier extends SplObjectStorage
{
private $_items;
public function attach($i)
{
if (!$i instanceof Item) {
throw new Exception('Item requis');
}
return parent::attach($i);
}
public function detach($i)
{
if (!$i instanceof Item) {
throw new Exception('Item requis');
}
return parent::detach($i);
}
public function calculTotal()
{
foreach ($this as $item) {
$somme[] = $item->price;
}
return array_sum($somme);
}
}
|
La méthode attach() se charge de ne pas stocker deux mêmes instances (aucune exception n'est retournée). Quant à detach(), elle se charge de retrouver l'objet
qu'on lui passe en paramètre (s'il existe) pour le supprimer du conteneur.
Cette classe est bien plus pratique qu'il n'y parait, elle peut même servir de support pour un design pattern registre.
II-Q. Fonctions de la SPL
L'extension SPL rajoute des classes et des interfaces à PHP, mais pas seulement : quelques fonctions existent aussi.
La plus intéressante reste sans aucun doute iterator_to_array(), qui prend en paramètre un itérateur et le parcourt totalement pour sortir ses résultats sous forme de tableau. En gros : ceci évite un foreach inutile juste pour regarder
les résultats :
Suivant le même exemple : iterator_count($iterator) compte le nombre d'élément dans la structure itérable.
spl_object_hash() retourne un identifiant unique pour un objet. 2 même instances mémoires auront les même identifiant. Extrêmement pratique pour stocker un objet et générer une "clé de rangement".
spl_autoload_register() permet de gérer une pile d'autoloads (fonctions étant chargées de charger une classe de manière automatique)
III. Conclusion
Non, PHP ne sera jamais un langage "orienté objet" (tel que java), et restera un langage 'fonctionnel' (basé sur des fonctions dans un contexte global); mais on perçoit nettement depuis PHP5, et les supérieurs (5.1 , 5.2), la volonté des développeurs et contributeurs du PHPGroup de fournir de vraies solutions aux programmeurs Objet, qui sont de plus en plus nombreux, et exigeants.
PHP5 est réellement capable en entreprise, et a atteint un niveau permettant de concevoir des systèmes complexes, et favorisant nettement le travail en équipe.
Car en utilisant massivement la SPL, on arrive à un taux de réutilisation de code très élevé, et à une interface commune d'accès « aux données » , au sens le plus large possible; le tout de manière très intuitive et proche de Java, C++ ou C#.
Souvenez vous de la règle du développeur : au moins on en écrit, au plus le risque de bug est faible.
La SPL propose des solutions qui sont intégrées directement dans le moteur Zend Engine 2, et qui font réagir foreach (par exemple) ou même les accesseurs de tableau pourtant banals [ et ].
Elle est écrite en C (en grande partie) et donc compilée : absolument aucun problème de performance; Zend Engine 2 a d'ailleurs été crée dans l'optique de supporter le modèle objet actuel de PHP(5).
De plus, si vous voulez lire sa source, aucun problème,
passez donc par là pour une traduction PHP.
PHP est opensource, la consultation des sources est très utile pour la SPL, car certaines sources sont carrément écrites en PHP (le reste en C), il suffit de fouiller le dépôt cvs, branche
php-src/ext/spl/internal, on voit alors le code(PHP) de IteratorIterator (entres autres).
On voit aussi beaucoup d'autres exemples que l'on peut utiliser ou modifier comme on le sent. Marcus répond aussi aux questions sur la mailing list Internal, de PHP.
Remarquez aussi : un PDOStatement, ou un SimpleXMLElement implémentent l'interface « Traversable », l'interface au sommet de la SPL, significative pour le Zend Engine 2. En fait, le PHPGroup utilise la SPL dans certaines extensions. Il existe par exemple un SimpleXMLIterator...
Nous n'avons pas tout vu sur la SPL, mais c'est un bon début pour commencer, donc usez et abusez de cette extension qui permet de créer des structures réellement agréables à manipuler et à maintenir.
PHP 5.3 introduit lui aussi de nouveaux objets SPL, souvenez-vous que rester à jour sur la version de PHP est là aussi gage de qualité de vos programmes, car plus d'objets disponibles, et moins buggués.


Copyright © 2008 . Aucune reproduction, même partielle, ne peut être faite
de ce site et de l'ensemble de son contenu : textes, documents, images, etc
sans l'autorisation expresse de l'auteur.
Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E
de dommages et intérêts.
Cette page est déposée à la
SACD.