บทนำ
การวนรอบข้อมูลจำนวนมากด้วย foreach ต้องใช้ Memory และเวลามาก ด้วย Generators สามารถ Iterate ได้โดยไม่มี Overhead เหล่านี้ Generator Function คล้าย Function ธรรมดา แต่แทน return ใช้ yield เพื่อคืนค่าทีละค่าและ Pause การทำงาน
yield เป็นหัวใจของ Generator - คล้าย return แต่ไม่หยุดการทำงาน คืนค่าสำหรับ Iteration รอบถัดไป แล้ว Pause รอรอบต่อไป
Yielding Values
For Loop yield ค่าใน Generator Function:
<?php
function squareGenerator() {
for ($i = 1; $i <= 5; $i++) {
yield $i * $i;
}
}
$gen = squareGenerator();
foreach ($gen as $val) {
echo $val . " ";
}
?>
ผลลัพธ์
1 4 9 16 25
เมื่อ Foreach พยายามแสดง $val ครั้งแรก Generator Yield Element แรก เก็บ $i ไว้ Pause จนกว่า Foreach จะขอรอบถัดไป
Implement range() ด้วย Generator
PHP range() คืน Array ทั้งหมด Generator ทำแบบ Lazy:
<?php
function rangeGenerator($start, $stop, $step) {
for ($i = $start; $i <= $stop; $i += $step) {
yield $i;
}
}
foreach (rangeGenerator(2, 10, 2) as $val) {
echo $val . " ";
}
?>
ผลลัพธ์
2 4 6 8 10
Associative Array Generator
<?php
function arrGenerator($arr) {
foreach ($arr as $key => $val) {
yield $key => $val;
}
}
$arr = ["one" => 1, "two" => 2, "three" => 3, "four" => 4];
$gen = arrGenerator($arr);
foreach ($gen as $key => $val) {
echo $key . "=>" . $val . "\n";
}
?>
ผลลัพธ์
one=>1 two=>2 three=>3 four=>4
Key Features ของ Generators
- Memory Efficient - ไม่เก็บข้อมูลทั้งหมดใน Memory
- Lazy Evaluation - คำนวณค่าเมื่อถูกขอเท่านั้น
- Can Yield Keys -
yield $key => $value - Return Value (PHP 7+) - ใช้
returnคืนค่าสุดท้าย ได้ผ่าน$gen->getReturn() - Send Values (PHP 7+) -
$gen->send($value)ส่งค่าเข้า Generator
ตัวอย่าง Return Value
<?php
function gen() {
yield 1;
yield 2;
return "done";
}
$gen = gen();
foreach ($gen as $val) {
echo $val . "\n";
}
echo "Return: " . $gen->getReturn();
?>
ผลลัพธ์
1 2 Return: done
เมื่อไหร่ควรใช้ Generators
- ประมวลผลไฟล์ใหญ่ (CSV, Log Files)
- Database Results ขนาดใหญ่
- Infinite Sequences
- Transformation Pipelines