(PHP 5 >= 5.5.0, PHP 7, PHP 8)
Les générateurs fournissent une façon simple de mettre en place des itérateurs sans le coût ni la complexité du développement d'une classe qui implémente l'interface Iterator.
Un générateur offre un moyen pratique de fournir des données aux boucles foreach
sans
avoir à construire un tableau en mémoire à l'avance, ce qui pourrait amener le programme
à dépasser une limite de mémoire ou nécessiter un temps de traitement considérable pour les générer.
À la place, une fonction générateur peut être utilisée,
qui est identique à une
fonction normale,
mis à part le fait qu'au lieu de retourner
une seule fois, un générateur peut utiliser yield
autant de fois que nécessaire, afin de
fournir les valeurs à parcourir.
Comme avec les itérateurs, l'accès aléatoire aux données n'est pas possible.
Un exemple simple de ce mécanisme est la ré-implémentation de la fonction range() sous la forme d'un générateur. La fonction standard range() doit générer un tableau contenant chaque valeur, et le retourner, ce qui peut conduire à des tableaux de taille importante : par exemple, l'appel du code range(0, 1000000) peut consommer nettement plus de 100 Mo de mémoire.
Comme alternative, nous pouvons implémenter un générateur
xrange()
, qui n'aura en besoin mémoire que la seule
création d'un objet Iterator, et devra garder trace
en interne du statut courant du générateur, ce qui revient à une
consommation mémoire inférieure à 1 Ko.
Exemple #1 Implémentation de la fonction range() sous la forme d'un générateur
<?php
function xrange($start, $limit, $step = 1) {
if ($start <= $limit) {
if ($step <= 0) {
throw new LogicException('Step must be positive');
}
for ($i = $start; $i <= $limit; $i += $step) {
yield $i;
}
} else {
if ($step >= 0) {
throw new LogicException('Step must be negative');
}
for ($i = $start; $i >= $limit; $i += $step) {
yield $i;
}
}
}
/*
* Il est à noter que les fonctions range() et xrange() produisent le
* même affichage, ci-dessous.
*/
echo 'Nombres impairs à un seul chiffre depuis range() : ';
foreach (range(1, 9, 2) as $number) {
echo "$number ";
}
echo "\n";
echo 'Nombres impairs à un seul chiffre depuis xrange() : ';
foreach (xrange(1, 9, 2) as $number) {
echo "$number ";
}
?>
L'exemple ci-dessus va afficher :
Nombres impairs à un seul chiffre depuis range() : 1 3 5 7 9 Nombres impairs à un seul chiffre depuis xrange() : 1 3 5 7 9
Lorsqu'une fonction générateur est appelée, un objet de la classe interne Generator est retournée. Cet objet implémente l'interface Iterator de la même façon qu'un objet itérateur, qui avance uniquement, le ferait, et fournit les méthodes qui peuvent être appelées pour manipuler le statut du générateur, y compris l'envoi des valeurs et leurs retours.