![]()
Introduction à Standard PHP Library
Vous êtes ici : Accueil / Articles / Formations en PHP
Qu’est-ce que la SPL ?
La SPL est une libraire de fonctions PHP incluse par défaut dans PHP5. Elle permet de résoudre les problèmes parmi les plus courants. Cette librairie se focalise sur tout sur le contrôle des itérations. Bien que très peu connue des développeurs, elle a tout de suite été remarquée par les créateurs de frameworks qui l’ont utilisé notamment pour utiliser du avoir recours au lazy loading ( chargement à la demande ).
L’interface Countable
Cette interface permet de redéfinir la valeur retournée par la fonction count() appelée sur un objet. Il faut pour cela écrire la méthode count() dans la classe :
Il est alors possible d’appeler la méthode count() sur l’objet
L’interface Iterator
Cette interface va permettre de redéfinir les valeurs retournées lors du recours à la structure foreach. Il va falloir réimplémenter un certain nombre de méthodes, ce qui peut s’avérer assez lourd. Cependant, nous verrons ensuite quelques classes permettant de ne redéfinir que les méthodes voulues :
current()
Cette méthode retourne la valeur courante. Elle sera appelée dans un foreach ou un each()
key()
Retourne la clé de la position courante. Cette méthode est appelée avec la syntaxe foreach( $o as $cle => $value ).
next()
Cette méthode est appelée pour déplacer la position courante vers l’avant.
rewind()
Cette méthode est appelée au tout début de l’instruction foreach est sert à repositionner le pointeur au début du tableau.
valid()
Retourne un booléen pour préciser si la position courante du pointeur est valide ou non.
Attention aux amalgames
Certaines méthodes présentées précédemment ont des similarités de nom avec quelques fonctions PHP de manipulation de tableau, comme key(), next()... Les méthodes de l’interface Iterator ne sont pas appelées lors de l’utilisation de ces fonctions.
Exemple
class Test implements Iterator {
private $array = array( 'k1' => 'v1', 'k2' => 'v2');
public function current() {
return current($this->array);
}
public function key() {
return key($this->array);
}
public function next() {
return next($this->array);
}
public function rewind() {
reset($this->array);
}
public function valid() {
return current( $this->array );
}
}
$t = new Test();
foreach( $t as $k => $v ) {
echo "Cle: $k Valeur : $v\n";
}
?>
L’interface IteratorAggregate
Bien que très utile, l’interface Iterator est un peu lourde à utiliser si vous n’avez qu’un simple tableau à manipuler. L’interface IteratorAggregate permet de ne proposer qu’une méthode : getIterator() appelée au moment de l’instruction foreach, et permet d’utiliser une classe déjà implémentée comme ArrayIterator. Ainsi, la classe suivante est l’équivalent de la précédente :
L’interface ArrayAccess
Nous avons vu comment redéfinir les actions lors de l’utilisation d’une structure itérative. Il manque une syntaxe pour reproduire un tableau à partir d’une classe : la syntaxe [] pour accéder aux éléments par leur index. Ce manque est comblé par l’interface ArrayAccess :
bool offsetExists( mixed )
Cette méthode précise si la clé utilisée existe. Retourne un booléen. Elle est appelée lors de l’utilisation de la fonction isset().
mixed offsetGet( mixed )
Retourne la valeur correspondant à la clé passée en paramètre. Cette méthode est appelée par la syntaxe []
mixed offsetSet( mixed, mixed )
Définit une valeur correspondant à la clé passée en premier argument, et retourne la valeur. Cette méthode est appelée avec l’opérateur d’affectation et la syntaxe [].
void offsetUnset( mixed )
Supprime l’association clé-valeur dont la clé est passée en paramètres. Cette méthode est appelée avec la fonction unset().
Exemple :
class Test implements ArrayAccess {
private $array = array( 'k1' => 'v1', 'k2' => 'v2');
public function offsetExists( $k ) {
echo "ok";
return isset( $this->array[ $k ] );
}
public function offsetGet( $k ) {
return $this->array[ $k ];
}
public function offsetSet( $k, $v ) {
$this->array[ $k ] = $v;
}
public function offsetUnset( $k ) {
unset( $this->array[ $k ] );
}
}
$t = new Test();
if( isset( $t['k1'] ) ) {
echo $t['k1'];
unset( $t['k1'] );
}
?>
La classe ArrayObject
Cette classe se comporte exactement comme un tableau, à la différence près que c’est un objet. L’avantage ? les tableaux ont des passages par valeur par défaut alors qu’un objet n’est passé que par référence. L’opérateur d’égalité réagira différemment en fonction du fait que cela soit un tableau ou un objet.
Spécifier plusieurs fonctions autoload()
La fonction __autoload()
Il existe depuis PHP 5 une fonction spéciale, __autoload() appelée lors d’une instanciation si une classe n’a pas encore été définie. Elle permet de charger la classe « à la volée » en incluant le fichier contenant le déclaration de la classe. Sa définition est souvent la suivante :
function __autoload( $className ) {
require_once $className . '.class.php';
}
// Va essayer d?inclure le fichier MaClasse.class.php
// Pour charger la classe à la volée
$maClasse = new MaClasse();
?>
Les limites de cette fonction
Cette fonction trouve ses limites dans la programmation modulaire : les répertoires contenant les classes sont souvent dans des dossiers différents suivant les modules, et la définition de la fonction __autoload() peut entraîner des conflits entre ceux-ci. Il devient donc nécessaire de pouvoir spécifier plusieurs fonctions __autoload() pour que chaque module puisse utiliser la fonctionnalité.
La fonction spl_autoload_register()
SPL propose une fonction nommée spl_autoload_register() dont le prototype est le suivant :
bool spl_autoload_register ([ mixed $autoload_function ] )
?>
Comme le montre son prototype, cette fonction permet d’ajouter des fonctions qui seront appelées lors du chargement à la volée. Si la classe n’est pas trouvée par une fonction, la suivante est évaluée. Cette fonction n’exclus évidemment pas les conflits de nom entre les classes. Il est pour cela conseillé de s’astreindre à un nommage très strict en préfixant ses classes par le nom du module. Ce problème tendra à disparaître avec les espaces de nommage introduits en PHP 6.
SPL fournit d’autres fonctions, notamment pour lister les fonctions de chargement et pour en ôter.
Implémenter du lazy loading avec SPL
Un des principaux avantages des itérateurs réside dans l’utilisation du lazy loading. Prenons un exemple concret : Nous voulons développer une classe pour interagir avec une base de données. Les transferts sont lents et il est préférable d’éviter les requêtes inutiles. Il devient alors utile d’avoir recours aux itérateurs pour n’effectuer la requête que si un foreach est exécuté. C’est notamment le choix de la librairie PHP:DBO.
Pour implémenter du lazy loading, nous avons besoin de d’un getter, et d’une variable pour stocker la donnée une fois chargée afin d’éviter de la recharger la fois suivante. Pour plus de clarté, nous avons rajouté une méthode privée de chargement de données, et qui ne doit être appelée qu’une fois.
class LazyLoading {
private function loadData() {
// Recuperation des données
}
public function getData() {
if( !$this->data ) {
$this->data = $this->loadData();
}
return $this->data;
}
}
?>
Le fait que la méthode loadData() soit en private empêche le développeur d’y avoir accès en dehors de la classe. Nous voyons clairement que si celui-ci ne fait pas appel à la méthode getData(), les données ne seront jamais importées.
Pour accéder aux données, la syntaxe sera la suivante :
$test = new LazyLoading();
foreach( $test->getData() as $cle => $valeur ) {
// Utilisation des données
echo $valeur;
}
?>
Cependant, cette méthode de lazy loading nous oblige à appeler la méthode getData(). Grâce à SPL, ce n’est plus nécessaire :
class LazyLoading implements IteratorAggregate {
private function loadData() {
// Recuperation des données
}
public function getIterator() {
if( !$this->data ) {
$this->data = $this->loadData();
}
return new ArrayIterator( $this->data );
}
}
?>
Pour accéder aux données, la syntaxe sera la suivante :
$test = new LazyLoading();
foreach( $test as $cle => $valeur ) {
// Utilisation des données
}
?>
Liens
http://www.phpriot.com/articles/oop-with-spl-php-5/1
http://www.php.net/ helly/php/ext/spl/



