Utiliser l'interface Iterator avec PHP 5

Rechercher

Utiliser l'interface Iterator avec PHP 5

  • Par Palleas
  • 9 commentaires
  • 28892 lectures
  • RSS -  Atom

PHP 5 a apporté son lot de nouveautés en matière de programmation orientée objet, notamment la possibilité d'utiliser des Interfaces. Iterator en est une et nous allons voir comment l'utiliser grâce à ce tutoriel. La structure conditionnelle " foreach " vous permettait jusqu'à lors de parcourir le contenu d'un tableau. Avec la version 5 de PHP, vous pouvez désormais parcourir tout un objet pour récupérer ses propriétés.

Rappel sur les Interfaces

Une interface est une manière de passer un contrat avec une classe, afin de s'assurer que celle-ci disposera bien de certaines méthodes/propriétés. Contrairement à l'héritage, il est possible d'implémenter plusieurs interfaces[1], ce qui permet de pallier à l'impossibilité d'utiliser l'héritage multiple en PHP.

L'interface Iterator

L'interface native Iterator existe depuis déjà quelques temps en java et apporte un atout non négligeable en matière de programmation orientée objet. Voici ce à quoi ressemble le code de l'interface Iterator :

<?php
Interface Iterator {
public function rewind();
public function key();
public function current();
public function next();
public function valid();
}
?>

Parcourir un objet avec l'instruction foreach()

<?php
class MaClasse {
protected $arg1 = 'plop' ;
protected $arg2 = 'plip';
//...
}
$c = new MaClasse();
foreach($c as $key=>$value) {
echo $key, ' : ', $value, '<br/>';
}
?>

Ce qui affichera :

arg1 : plop
arg2 : plip

C'est là qu'intervient l'interface Iterator. Elle va en effet vous permettre de personnaliser le comportement de foreach. Implémenter cette interface dans votre classe vous oblige de surcharger (ou redéfinir) les 5 methodes suivantes : rewind(), next(), key(), current() et valid().

<?php
class MaClasse implements Iterator {
protected $n;
const MAX = 5;
public function rewind() {
$this->n = 0;
}
public function next() {
$this->n++;
}
public function key() {
return 'increment '.$this->n+1;
}
public function current() {
return $this->n;
}
public function valid() {
return $this->n<=self::MAX;
}
}
$c = new MaClasse();
foreach($c as $key => $val) {
echo $key,' : ',$val, '<br/>';
}
?>

Ce qui affichera :

increment 1 : 0
increment 2 : 1
increment 3 : 2
increment 4 : 3
increment 5 : 4

Ces méthodes seront appelées par foreach, dans cet ordre :

  1. rewind lors de la première iteration, qui vous permet de rembobiner votre objet (ici on remet $n à 0)
  2. valid qui vérifie que l'on n'est pas arrivé à la fin de notre itération (ici que $n est inferieur au nombre maximum d'itération fixé par la constante MAX). Si valid retourne TRUE, on poursuit sinon on s'arrête, c'est la fin de l'itération.
  3. current qui retourne la valeur de l'itération courante (ici $n)
  4. key qui retourne la clé de l'itération courante (ici key.$n )
  5. next qui lance l'itération suivante (ici, on incrémente $n de 1)
  6. Est en suite rappelée la méthode valid() qui vérifie une nouvelle fois que l'on n'est pas arrivé aux termes de l'Itération.

Note [1] : Une classe ne peut cependant pas implémenter deux interfaces partageant des noms de fonctions.

En savoir plus sur l'interface Iterator



Les commentaires

1. Par BLANCHON Vincent le 17/06/2008 16:22

Dans tes liens pour en savoir plus il y en a deux de mauvais : il y a un "#%20" qui traine avant l'url.

2. Par Emacs le 17/06/2008 19:17

Arf... merci

3. Par Benjamin le 30/06/2008 16:56

Merci pour tes tutos

4. Par Céline le 22/09/2008 15:40

Franchement, j'ai juste survolé l'ensemble des tuto sur l'objet mais j'ai déjà trouvé mon bonheur. Je vais y regarder de plus près. C'est génial. J'étais complètement perdue avec certaines notions et je sens que tout va s'éclaircir prodigieusement.
L'idéal (mais j'ai cru comprendre que tu n'avais plus trop de temps) aurait été de conclure l'ensemble par un cas concret, une petite application toute simple en objet car contrairement à ce que tu as dit dans un de tes commentaires ça ne se trouve pas du tout facilement sur le web : que des histoires de voiture, de légumes sans lien avec les applications réelles. J'ai pourtant cherché des soirées entières. Mais je sais j'en demande surement trop.
En tout cas mille mercis.

5. Par Jipe le 08/04/2009 14:50

Merci pour ce tutoriel vraiment génial qui m'a permis de beaucoup mieux comprendre le principe de la POO. Cependant je reste très sceptique devant ce dernier tutoriel car je ne comprend pas bien à quoi cela peut bien servir dans la pratique…

6. Par Emacs le 08/04/2009 22:22

@Jipe : ça peut entre autre permettre de parcourir une collection d'objets (un objet qui contient des objets) ou bien parcourir un jeu de résultats d'enregistrements de bases de données récupérés avec MySQLi ou PDO.

7. Par thierry le 20/05/2009 17:25

En théorie une interface est une sorte de contrat (comme souligné au début de ce tuto), donc normalement si j'enlève le "implements Iterator" tout en gardant les méthodes implémentés cela devrait encore fonctionner non (or ce n'est pas le cas) ?

8. Par thierry le 20/05/2009 17:41

D'autre part j'ai testé le 1er exemple qui implémente Iterator, et je n'obtiens pas le résultat attendu.

A la sortie standard j'ai :
1 : 0
1 : 1
1 : 2
1 : 3
1 : 4
1 : 5

au lieu de

increment 1 : 0
increment 2 : 1
increment 3 : 2
increment 4 : 3
increment 5 : 4

(j'ai pourtant simplement copié/collé le code :/)

9. Par thierry le 20/05/2009 17:49

J'ai finalement compris.

Il faut mettre $this->n+1 entre parenthèse dans la fonction key (sinon la concaténation a lieu avant l'addition).

Une autre petite coquille, dans le 1er exemple avec la classe MaClasse (sans Iterator), le foreach n'affiche rien car les attributs ne sont pas déclarés public)