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
3Der 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: BobUm 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.
Aufgabe
EinfachErstelle 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 eineProduct-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 eineInventory-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(): Generatorbesitzen, die jedes Produkt einzeln liefert - Eine Generatormethode
expensiveProducts(float $minPrice): Generatorbesitzen, 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.- SKU:
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
?>Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in OOPKlassen vs. ObjekteDas Schlüsselwort $thisMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick – Einfacher Taschenrechner4Vererbung
Grundlegende VererbungDas Schlüsselwort parent::MethodenüberschreibungDas Schlüsselwort finalAbstrakte KlassenRückblick – Mitarbeiterhierarchie7Kapselung
Öffentlich, geschützt, privatZugriffsmodifikatoren im DetailGetter und SetterInformationsverbergungKonstruktor-Promotion (8.0)Wiederholung – System zur Verwaltung von Schülerdatensätzen10Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungDependency InjectionAnonyme KlassenEnums (PHP 8.1)Fibers (PHP 8.1)Objektklonen im DetailGeneratoren & Iteratoren2Namespaces & Autoloading
Einführung in NamespacesDas use-SchlüsselwortPSR-4-Autoloading-StandardComposer-AutoloaderRückblick – Organisiertes Projekt5Schnittstellen & Verträge
Einführung in SchnittstellenSchnittstellen implementierenMehrere Schnittstellen implementierenSchnittstelle vs. abstrakte KlasseTyp-Hinweise mit SchnittstellenRückblick – Formrechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objektklonen__serialize & __unserializeRückblick – Benutzerdefinierte Sammlung11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenBenutzerdefinierte Exception-HierarchieTry, Catch, FinallyRückblick – Formularvalidator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klassen-Eigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenSchreibgeschützte Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphie
Methodenüberschreibung erneut betrachtetPolymorphie über SchnittstellenTyp-Hinweise & Union-TypenSpätes statisches BindenRückblick – Zahlungsabwickler9Traits
Einführung in TraitsMehrere Traits verwendenAuflösung von Trait-KonfliktenAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschließende Herausforderungen
E-Learning-PlattformBankingsystemEntwicklung einer SpielfigurFahrzeugvermietungÜbe selbstständig: Online-PHP-Compiler