← Tilbage til koncepter
Generators & Iterators
Memory-effektiv iteration med yield keyword, generator functions og generator delegation i PHP
Kategori: Fundamentals
🎯 Key Points
- ✓yield keyword - Producerer værdier én ad gangen i stedet for at returnere hele array
- ✓Memory efficiency - Kun én værdi i memory ad gangen, perfekt til store datasæt
- ✓Lazy evaluation - Værdier genereres on-demand når de anmodes
- ✓Generator delegation (yield from) - Delegér iteration til anden generator eller iterable
- ✓send() method - Send værdier tilbage til generator under iteration
- ✓Generator return values - Returnér final value efter iteration er færdig
- ✓Iterator interface - Generators implementerer automatisk Iterator interface
- ✓Bidirectional communication - To-vejs kommunikation mellem caller og generator
- ✓Infinite sequences - Generér uendelige sekvenser uden memory issues
- ✓File processing - Læs store filer linje for linje uden at loade alt i memory
- ✓throw() method - Kast exceptions ind i generator for error handling
- ✓State preservation - Generator bevarer state mellem yield calls
💻 Kode Eksempel
<?php
// Basic generator for range
function generateRange(int $start, int $end, int $step = 1): Generator {
for ($i = $start; $i <= $end; $i += $step) {
yield $i;
}
}
// Generator for reading large files line by line
function readLargeFile(string $filename): Generator {
$handle = fopen($filename, 'r');
if (!$handle) {
throw new RuntimeException("Cannot open file: {$filename}");
}
try {
while (($line = fgets($handle)) !== false) {
yield trim($line);
}
} finally {
fclose($handle);
}
}
// Generator delegation with yield from
function generateAlphabet(): Generator {
yield from range('a', 'z');
}
function generateAlphaNumeric(): Generator {
yield from generateAlphabet();
yield from range(0, 9);
}
// Generator with send() for bidirectional communication
function logger(): Generator {
$logLevel = 'INFO';
while (true) {
$message = yield;
echo "[{$logLevel}] {$message}\n";
// Check if new log level was sent
$newLevel = yield;
if ($newLevel !== null) {
$logLevel = $newLevel;
}
}
}
// Generator with return value
function processData(array $data): Generator {
$sum = 0;
foreach ($data as $item) {
$sum += $item;
yield $item * 2;
}
return $sum; // Return value after iteration
}
// Usage examples
echo "=== Range Generator ===\n";
foreach (generateRange(1, 5) as $num) {
echo "Number: {$num}\n";
}
echo "\n=== Generator Delegation ===\n";
$count = 0;
foreach (generateAlphaNumeric() as $char) {
echo $char . " ";
if (++$count % 10 === 0) echo "\n";
}
echo "\n\n=== Generator with Return ===\n";
$gen = processData([1, 2, 3, 4, 5]);
foreach ($gen as $value) {
echo "Processed: {$value}\n";
}
echo "Sum: {$gen->getReturn()}\n";💼 Hvornår bruges det?
- •Læsning af store log filer eller CSV filer linje for linje uden at loade hele filen i memory
- •Database result pagination hvor kun current page's rows er i memory ad gangen
- •API response streaming hvor data sendes til klient i chunks i stedet for at vente på komplet response
- •Fibonacci sequences og andre matematiske serier der kan være uendelige eller meget store
- •ETL processes hvor data transformeres on-the-fly under iteration uden intermediate storage
- •Async operations i ReactPHP eller Amphp hvor generators bruges til coroutines og concurrent tasks
⭐ Best Practices
- ✓Brug generators til store datasæt - hvis array er > 10,000 items eller > 1MB, overvej generator
- ✓Kombiner yield from for at delegere til andre generators eller iterables for bedre composition
- ✓Brug finally blocks når generators arbejder med resources (files, connections) for proper cleanup
- ✓Type hint return type som Generator for bedre IDE support og documentation
- ✓Undgå kompleks state management i generators - hold dem simple og fokuserede
- ✓Brug generator return values til at kommunikere summary statistics efter iteration
- ✓Test generators med iterator_to_array() i unit tests, men vær opmærksom på memory usage
- ✓Dokumentér hvad generator yielder (key/value types) med @return Generator<key, value> PHPDoc
ℹ️ Quick Info
Kategori
Fundamentals
Sværhedsgrad
Mellem til Avanceret