Menu
Coddy logo textTech

Generatoren & Iteratoren

Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 62 von 91.

Generatoren bieten eine einfache Möglichkeit, Iteratoren zu erstellen, ohne die vollständige Iterator-Schnittstelle zu implementieren. Eine Generatorfunktion verwendet yield anstelle von return, um Werte einzeln zu erzeugen, und pausiert die Ausführung zwischen den einzelnen Werten.

Hier ist ein einfacher Generator, der eine Zahlenfolge erzeugt:

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

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

Ausgabe:

1
2
3

Der entscheidende Vorteil ist die Speichereffizienz. Anstatt ein vollständiges Array im Speicher aufzubauen, erzeugen Generatoren Werte nach Bedarf. Das ist bei der Arbeit mit großen Datensätzen entscheidend – ein Generator, der eine Million Datensätze verarbeitet, verwendet genauso viel Speicher wie einer, der zehn verarbeitet.

Generatoren können auch Schlüssel-Wert-Paare liefern:

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

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

Ausgabe:

admin: Alice
editor: Bob

Um deine eigenen Klassen mit foreach iterierbar zu machen, implementiere das Iterator-Interface. In den meisten Fällen bieten Generatoren jedoch eine sauberere Lösung mit weniger Boilerplate-Code. Sie sind besonders in der OOP nützlich, wenn eine Klasse eine collection von Elementen bereitstellen muss, ohne alles auf einmal in den Speicher zu laden.

challenge icon

Aufgabe

Einfach

Erstelle ein Produktinventarsystem, das Generatoren verwendet, um effizient durch große Sammlungen zu iterieren, ohne alles auf einmal in den Speicher zu laden. Du erstellst eine Klasse, die Produkte speichert und Generatormethoden bereitstellt, um auf verschiedene Arten durch sie zu iterieren.

Du organisierst deinen Code über drei Dateien:

  • Product.php: Erstelle eine Product-Klasse, die einen Artikel im Inventar darstellt. Verwende Konstruktor-Promotion, um eine öffentliche Eigenschaft $sku (string), eine öffentliche Eigenschaft $name (string) und eine öffentliche Eigenschaft $price (float) zu definieren.
  • Inventory.php: Erstelle eine Inventory-Klasse, die eine Sammlung von Produkten verwaltet und Generatormethoden bereitstellt, um durch sie zu iterieren. Binde die Product-Datei ein. Die Klasse sollte:
    • Eine private Array-Eigenschaft zum Speichern von Produkten besitzen
    • Eine Methode addProduct(Product $product) besitzen, die ein Produkt zur Sammlung hinzufügt
    • Eine Generatormethode allProducts(): Generator besitzen, die jedes Produkt einzeln liefert
    • Eine Generatormethode expensiveProducts(float $minPrice): Generator besitzen, die nur Produkte mit einem Preis größer oder gleich dem angegebenen Mindestpreis liefert und dabei Schlüssel-Wert-Paare erzeugt, wobei der Schlüssel der SKU und der Wert das Produkt ist
  • main.php: Binde die Inventory-Datei ein. Du erhältst eine Eingabe: einen Mindestpreisschwellenwert.

    Erstelle ein Inventory-Objekt und füge diese drei Produkte hinzu:

    • SKU: "A001", Name: "Laptop", Preis: 999.99
    • SKU: "A002", Name: "Mouse", Preis: 29.99
    • SKU: "A003", Name: "Monitor", Preis: 349.99

    Iteriere zuerst durch allProducts() und gib den Namen jedes Produkts in einer eigenen Zeile aus.

    Gib anschließend eine leere Zeile aus und iteriere danach mithilfe des Eingabeschwellenwerts durch expensiveProducts(). Gib für jedes teure Produkt "[sku]: [name] - $[price]" in einer eigenen Zeile aus. Formatiere den Preis mit genau 2 Dezimalstellen.

Diese Herausforderung zeigt, wie Generatoren das verzögerte Iterieren durch Sammlungen ermöglichen: Jedes Produkt wird erst dann geliefert, wenn es angefordert wird, wodurch dieser Ansatz für große Inventare speichereffizient ist. Die Schlüssel-Wert-Ausgabe in expensiveProducts() zeigt, wie Generatoren strukturierte Iterationsdaten bereitstellen können.

Probier es selbst

<?php

require_once 'Inventory.php';

// Eingabe lesen
$minPrice = floatval(trim(fgets(STDIN)));

// TODO: Erstelle eine Inventory-Instanz

// TODO: Füge drei Produkte hinzu:
// SKU: "A001", Name: "Laptop", Price: 999.99
// SKU: "A002", Name: "Mouse", Price: 29.99
// SKU: "A003", Name: "Monitor", Price: 349.99

// TODO: Iteriere durch allProducts() und gib den Namen jedes Produkts aus

// TODO: Gib eine leere Zeile aus

// TODO: Iteriere durch expensiveProducts() unter Verwendung von $minPrice
// Für jedes teure Produkt gib "[sku]: [name] - $[price]" aus
// Formatiere den Preis mit genau 2 Dezimalstellen

?>
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-PHP-Compiler