#Generator là gì?
Generator là một cách để trả về từng phần dữ liệu (lazy) thay vì toàn bộ array.
👉 Dùng yield thay vì return
#Bad Example (Anti-pattern)
function getAllUsers(PDO $pdo): array
{
return $pdo->query('SELECT * FROM users')->fetchAll();
}
Vấn đề
- Load toàn bộ data vào RAM
- Dataset lớn → crash
- Không scalable
#Good Example (Best Practice)
#1. File processing
function readLines(string $path): \Generator
{
$handle = fopen($path, 'r');
try {
while (($line = fgets($handle)) !== false) {
yield trim($line);
}
} finally {
fclose($handle);
}
}
👉 Đọc từng dòng → memory constant
#2. Database chunking
function getAllUsers(PDO $pdo, int $chunk = 1000): \Generator
{
$offset = 0;
do {
$stmt = $pdo->prepare('SELECT * FROM users LIMIT :l OFFSET :o');
$stmt->bindValue(':l', $chunk, PDO::PARAM_INT);
$stmt->bindValue(':o', $offset, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll();
foreach ($rows as $row) {
yield User::fromArray($row);
}
$offset += $chunk;
} while (count($rows) === $chunk);
}
#3. Lazy range
function lazyRange(int $start, int $end): \Generator
{
for ($i = $start; $i <= $end; $i++) {
yield $i;
}
}
#4. Chain generator
function activeUsers(PDO $pdo): \Generator
{
foreach (getAllUsers($pdo) as $user) {
if ($user->isActive()) {
yield $user;
}
}
}
#Giải thích sâu
#1. Lazy evaluation
Generator chỉ tạo giá trị khi cần
👉 Không compute trước
#2. Memory model
- Array → O(n)
- Generator → O(1)
👉 Khác biệt cực lớn với big data
#3. Streaming mindset
Generator = stream data
👉 Phù hợp:
- File lớn
- API stream
- Queue processing
#4. yield vs return
return: kết thúc functionyield: pause và resume
👉 Function trở thành iterator
#5. yield from
yield from anotherGenerator();
👉 Compose dễ dàng
#Tips & Tricks (Senior level)
#1. Rule
👉 Dataset lớn → dùng generator
#2. Laravel
cursor()thay choget()
User::cursor()->each(fn($u) => ...);
#3. Không dùng cho mọi case
👉 Small dataset → array vẫn ok
#4. Debug khó hơn
👉 Vì lazy → không thấy data ngay
#5. Kết hợp pipeline
Generator + filter + map → giống stream processing
#Interview Questions
1. Generator là gì?
Summary:
- Trả dữ liệu từng phần
Deep: Dùng yield → không load toàn bộ vào memory
2. Generator vs array?
Summary:
- Generator tiết kiệm RAM
Deep: Array load toàn bộ, generator lazy load
3. Khi nào nên dùng generator?
Summary:
- Dataset lớn
Deep: File lớn, DB lớn, streaming
4. yield from là gì?
Summary:
- Chain generator
Deep: Delegate iteration cho generator khác
5. Nhược điểm của generator?
Summary:
- Debug khó
Deep: Lazy → không thấy data ngay, khó trace
#Kết luận
👉 Generator giúp:
- Tiết kiệm memory
- Scale với dataset lớn
- Code theo kiểu stream
Nếu bạn xử lý data lớn mà vẫn dùng array → sớm muộn cũng crash