while (condition) { ... } chạy khối lệnh hết lần này đến lần khác chừng nào điều kiện còn đúng. Điều kiện được kiểm tra trước mỗi lần lặp, nên nếu ngay từ đầu nó đã sai thì thân vòng lặp không bao giờ chạy. Phải có thứ gì đó bên trong vòng lặp thay đổi điều kiện, nếu không vòng lặp sẽ không bao giờ kết thúc.
Đây đúng là loại câu hỏi mà while sinh ra để giải: bạn không biết trước số lần lặp, chỉ biết khi nào cần dừng. Thử đổi lãi suất rồi chạy lại.
do while: chạy ít nhất một lần
do { ... } while (condition); kiểm tra điều kiện sau thân vòng lặp, nên thân vòng lặp luôn chạy một lần. Chú ý dấu chấm phẩy ở cuối.
Cách dùng điển hình là "thử trước, kiểm tra sau": tung xúc xắc cho đến khi ra mặt sáu, tạo mã cho đến khi gặp mã chưa dùng. Lần thử đầu tiên phải diễn ra trước khi có gì đó để kiểm tra. Ví dụ này cho kết quả khác nhau sau mỗi lần chạy:
while (true) với break
Khi điều kiện thoát dễ kiểm tra hơn ở giữa thân vòng lặp, hãy viết while (true) và thoát ra bằng break. continue nhảy sang lần kiểm tra tiếp theo, giống như trong mọi vòng lặp khác.
array_shift() trả về null khi mảng đã rỗng, đó là lối thoát còn lại. Vòng lặp này cũng có thể viết thành while ($queue), vì mảng rỗng được coi là false.
Đọc tệp từng dòng
fgets() trả về từng dòng một và trả về false khi hết tệp, nên có thể dùng trực tiếp để điều khiển vòng lặp while. Khối code dưới đây ghi tệp trước, rồi đọc lại.
Cặp ngoặc quanh $line = fgets($handle) rất quan trọng: phép gán diễn ra trước, sau đó kết quả mới được so sánh với false. Dùng !== false thay vì kiểm tra truthy thông thường giúp dòng cuối chỉ chứa 0 (không có ký tự xuống dòng phía sau) không làm vòng lặp kết thúc sớm. Trang fopen() trình bày các hàm làm việc với tệp.
while với endwhile trong template
Giống if và for, while có dạng dùng dấu hai chấm cho HTML: while (...): và endwhile;. Ví dụ này in một danh sách đếm ngược trong tab Trang.
Lỗi thường gặp: vòng lặp không bao giờ kết thúc
Biến đếm phải tiến dần về điều kiện thoát. Quên $i++, hoặc thay đổi nhầm biến, là điều kiện sẽ đúng mãi mãi. Trên máy chủ web, PHP dừng script sau max_execution_time (mặc định 30 giây) kèm một lỗi nghiêm trọng (fatal error). Trên dòng lệnh, script không bao giờ dừng.
// Never ends: $i is never changed
$i = 0;
while ($i < 3) {
echo $i;
}
Một giới hạn an toàn là cách bảo vệ đơn giản cho những vòng lặp phụ thuộc vào dữ liệu bên ngoài, như thử lại một lời gọi hoặc lấy kết quả theo từng trang:
Chạy vài lần: có lúc thành công sớm, có lúc bỏ cuộc, nhưng lần nào cũng kết thúc. Khi bạn biết trước số lần lặp, một vòng lặp for ghi điểm bắt đầu, điểm kết thúc và bước nhảy trên cùng một dòng, nên khó viết sai hơn.
Câu hỏi thường gặp
while và do while trong PHP khác nhau thế nào?
while kiểm tra điều kiện trước mỗi lần lặp, nên thân vòng lặp có thể không chạy lần nào. do { ... } while ($cond); kiểm tra sau mỗi lần lặp, nên thân vòng lặp luôn chạy ít nhất một lần. Chú ý dấu chấm phẩy sau điều kiện của do while.
Làm sao dừng một vòng lặp while vô hạn trong PHP?
Bên trong vòng lặp, kết thúc nó bằng break khi điều kiện thoát được thỏa mãn: while (true) { ...; if ($done) { break; } }. Nếu vòng lặp không có break và điều kiện không bao giờ thành false, script sẽ chạy cho đến khi max_execution_time của PHP dừng nó (với request web) hoặc chạy mãi mãi (với dòng lệnh).
Khi nào nên dùng while thay vì for trong PHP?
Dùng while khi bạn không biết cần bao nhiêu lần lặp: đọc đến hết tệp, thử lại cho đến khi thành công, xử lý hàng đợi cho đến khi rỗng. Dùng for khi bạn đếm, và foreach để duyệt qua mọi phần tử của mảng.
PHP có vòng lặp do until không?
Không. Hãy đảo ngược điều kiện dừng trong một do while: do { $n++; } while (!($n >= 3)); chạy cho đến khi $n >= 3 đúng. until không phải từ khóa của PHP.