Menu
Coddy logo textTech

Générateurs et itérateurs

Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy. Leçon 62 sur 91.

Les générateurs offrent un moyen simple de créer des itérateurs sans implémenter l’interface Iterator complète. Une fonction génératrice utilise yield au lieu de return pour produire les valeurs une par une, en interrompant l’exécution entre chaque valeur.

Voici un générateur de base qui produit une séquence de nombres :

<?php
function countTo(int $max): Generator {
    for ($i = 1; $i <= $max; $i++) {
        yield $i;
    }
}

foreach (countTo(3) as $number) {
    echo "$number\n";
}

Sortie :

1
2
3

Le principal avantage est l’efficacité de la mémoire. Au lieu de construire un tableau entier en mémoire, les générateurs produisent des valeurs à la demande. Cela est essentiel lorsque vous travaillez avec de grands ensembles de données : un générateur traitant un million d’enregistrements utilise la même quantité de mémoire qu’un générateur qui en traite dix.

Les générateurs peuvent également produire des paires clé-valeur :

<?php
function userGenerator(): Generator {
    yield 'admin' => 'Alice';
    yield 'editor' => 'Bob';
}

foreach (userGenerator() as $role => $name) {
    echo "$role: $name\n";
}

Sortie :

admin: Alice
editor: Bob

Pour rendre vos propres classes itérables avec foreach, implémentez l’interface Iterator. Cependant, dans la plupart des cas, les générateurs offrent une solution plus claire, avec moins de code passe-partout. Ils sont particulièrement utiles en OOP lorsqu’une classe doit exposer une collection d’éléments sans tout charger en mémoire en une seule fois.

challenge icon

Défi

Facile

Construisons un système d’inventaire de produits qui utilise des générateurs pour parcourir efficacement de grandes collections sans tout charger en mémoire en une seule fois. Tu vas créer une classe qui stocke les produits et fournit des méthodes génératrices pour les parcourir de différentes manières.

Tu vas organiser ton code sur trois fichiers :

  • Product.php : crée une classe Product qui représente un article de l’inventaire. Utilise la promotion des propriétés du constructeur pour définir un $sku (chaîne de caractères) public, un $name (chaîne de caractères) public et un $price (nombre à virgule flottante) public.
  • Inventory.php : crée une classe Inventory qui gère une collection de produits et fournit des méthodes génératrices pour les parcourir. Inclus le fichier Product. La classe doit :
    • Avoir une propriété privée de type tableau pour stocker les produits
    • Avoir une méthode addProduct(Product $product) qui ajoute un produit à la collection
    • Avoir une méthode génératrice allProducts(): Generator qui fournit chaque produit un par un
    • Avoir une méthode génératrice expensiveProducts(float $minPrice): Generator qui fournit uniquement les produits dont le prix est supérieur ou égal au minimum donné, en fournissant des paires clé-valeur où la clé est le SKU et la valeur est le produit
  • main.php : inclus le fichier Inventory. Tu recevras une entrée : un seuil de prix minimum.

    Crée un Inventory et ajoute ces trois produits :

    • SKU : "A001", Nom : "Laptop", Prix : 999.99
    • SKU : "A002", Nom : "Mouse", Prix : 29.99
    • SKU : "A003", Nom : "Monitor", Prix : 349.99

    Commence par parcourir allProducts() et afficher le nom de chaque produit sur sa propre ligne.

    Affiche ensuite une ligne vide, puis parcours expensiveProducts() en utilisant le seuil fourni en entrée. Pour chaque produit coûteux, affiche "[sku]: [name] - $[price]" sur sa propre ligne. Formate le prix avec exactement 2 décimales.

Ce défi montre comment les générateurs permettent de parcourir les collections de manière différée : chaque produit n’est fourni que lorsqu’il est demandé, ce qui rend cette approche efficace en mémoire pour les inventaires volumineux. La fourniture de paires clé-valeur dans expensiveProducts() montre comment les générateurs peuvent fournir des données d’itération structurées.

Essayez vous-même

<?php

require_once 'Inventory.php';

// Lire l'entrée
$minPrice = floatval(trim(fgets(STDIN)));

// TODO: Créer une instance d'Inventory

// TODO: Ajouter trois produits :
// SKU: "A001", Name: "Laptop", Price: 999.99
// SKU: "A002", Name: "Mouse", Price: 29.99
// SKU: "A003", Name: "Monitor", Price: 349.99

// TODO: Parcourir allProducts() et afficher le nom de chaque produit

// TODO: Afficher une ligne vide

// TODO: Parcourir expensiveProducts() en utilisant $minPrice
// Pour chaque produit cher, afficher "[sku]: [name] - $[price]"
// Formater le prix avec exactement 2 décimales

?>
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur PHP en ligne