Loops
Loops ใช้สำหรับทำซ้ำโค้ดหลายรอบ ในบทนี้เราจะเรียนรู้ loops ทุกประเภทใน PHP 8.4+ รวมถึง loop control statements
For Loop
Section titled “For Loop”ใช้เมื่อรู้จำนวนรอบที่ต้องการ:
<?php// for พื้นฐาน// for (เริ่มต้น; เงื่อนไข; เพิ่ม/ลด)for ($i = 0; $i < 5; $i++) { echo $i . " "; // 0 1 2 3 4}
// นับถอยหลังfor ($i = 5; $i >= 1; $i--) { echo $i . " "; // 5 4 3 2 1}
// เพิ่มทีละ 2for ($i = 0; $i <= 10; $i += 2) { echo $i . " "; // 0 2 4 6 8 10}
// หลายตัวแปรfor ($i = 0, $j = 10; $i < $j; $i++, $j--) { echo "($i, $j) "; // (0, 10) (1, 9) (2, 8) (3, 7) (4, 6)}
// Nested for loopfor ($row = 1; $row <= 3; $row++) { for ($col = 1; $col <= 3; $col++) { echo "[$row,$col] "; } echo "\n";}// [1,1] [1,2] [1,3]// [2,1] [2,2] [2,3]// [3,1] [3,2] [3,3]
// Loop กับ array (ใช้ foreach ดีกว่า)$fruits = ["apple", "banana", "orange"];for ($i = 0; $i < count($fruits); $i++) { echo $fruits[$i] . " ";}
// Optimize: cache count$count = count($fruits);for ($i = 0; $i < $count; $i++) { echo $fruits[$i] . " ";}Alternative Syntax
Section titled “Alternative Syntax”<?php// สำหรับ templates?><ul> <?php for ($i = 1; $i <= 5; $i++): ?> <li>Item <?= $i ?></li> <?php endfor; ?></ul>While Loop
Section titled “While Loop”ทำซ้ำจนกว่าเงื่อนไขจะเป็น false:
<?php// while พื้นฐาน$i = 0;while ($i < 5) { echo $i . " "; // 0 1 2 3 4 $i++;}
// อ่านไฟล์ทีละบรรทัด$file = fopen("data.txt", "r");while (!feof($file)) { $line = fgets($file); echo $line;}fclose($file);
// อ่านจาก database$stmt = $pdo->query("SELECT * FROM users");while ($row = $stmt->fetch()) { echo $row['name'] . "\n";}
// รอจนกว่าเงื่อนไขจะเปลี่ยน$attempts = 0;$maxAttempts = 3;$success = false;
while ($attempts < $maxAttempts && !$success) { $success = tryConnection(); if (!$success) { $attempts++; sleep(1); // รอ 1 วินาที }}
// Infinite loop (ระวัง!)// while (true) {// // ต้องมี break เพื่อออก// }Alternative Syntax
Section titled “Alternative Syntax”<?php$items = ["A", "B", "C"];$i = 0;?><ul> <?php while ($i < count($items)): ?> <li><?= $items[$i] ?></li> <?php $i++; ?> <?php endwhile; ?></ul>Do-While Loop
Section titled “Do-While Loop”ทำอย่างน้อย 1 รอบก่อนตรวจเงื่อนไข:
<?php// do-while - ทำอย่างน้อย 1 ครั้ง$i = 10;do { echo $i . " "; // 10 (แม้เงื่อนไขเป็น false) $i++;} while ($i < 5);
// ใช้กับ user input validationdo { echo "Enter a number (1-10): "; $input = (int) readline();} while ($input < 1 || $input > 10);
echo "You entered: $input";
// เปรียบเทียบ while กับ do-while$value = 10;
// while: ไม่ทำเลยwhile ($value < 5) { echo "while: $value\n"; // ไม่แสดง $value++;}
// do-while: ทำ 1 ครั้งdo { echo "do-while: $value\n"; // แสดง: do-while: 10 $value++;} while ($value < 5);Foreach Loop
Section titled “Foreach Loop”ใช้สำหรับ loop ผ่าน array และ iterable objects:
<?php// Indexed array$fruits = ["apple", "banana", "orange"];
foreach ($fruits as $fruit) { echo $fruit . " "; // apple banana orange}
// พร้อม indexforeach ($fruits as $index => $fruit) { echo "$index: $fruit\n";}// 0: apple// 1: banana// 2: orange
// Associative array$person = [ "name" => "John", "age" => 25, "city" => "Bangkok"];
foreach ($person as $key => $value) { echo "$key: $value\n";}// name: John// age: 25// city: Bangkok
// Nested arrays$users = [ ["name" => "Alice", "age" => 30], ["name" => "Bob", "age" => 25], ["name" => "Charlie", "age" => 35],];
foreach ($users as $user) { echo "{$user['name']} is {$user['age']} years old\n";}
// Destructuring (PHP 7.1+)foreach ($users as ["name" => $name, "age" => $age]) { echo "$name is $age years old\n";}Modifying Array in Foreach
Section titled “Modifying Array in Foreach”<?php$numbers = [1, 2, 3, 4, 5];
// ❌ การแก้ไขแบบนี้ไม่มีผลforeach ($numbers as $num) { $num = $num * 2; // $num เป็น copy}print_r($numbers); // ยังเป็น [1, 2, 3, 4, 5]
// ✅ ใช้ reference (&) เพื่อแก้ไขforeach ($numbers as &$num) { $num = $num * 2; // แก้ไขตรงๆ}unset($num); // สำคัญ! ควร unset หลังใช้ referenceprint_r($numbers); // [2, 4, 6, 8, 10]
// ✅ หรือใช้ key เพื่อแก้ไขforeach ($numbers as $key => $num) { $numbers[$key] = $num + 1;}Alternative Syntax
Section titled “Alternative Syntax”<?php$products = [ ["name" => "iPhone", "price" => 35000], ["name" => "Samsung", "price" => 25000],];?><table> <tr><th>Product</th><th>Price</th></tr> <?php foreach ($products as $product): ?> <tr> <td><?= $product['name'] ?></td> <td><?= number_format($product['price']) ?></td> </tr> <?php endforeach; ?></table>Loop Control Statements
Section titled “Loop Control Statements”ใช้ออกจาก loop ทันที:
<?php// break ออกจาก loopfor ($i = 1; $i <= 10; $i++) { if ($i === 5) { break; // ออกเมื่อ $i = 5 } echo $i . " "; // 1 2 3 4}
// break กับ nested loopsfor ($i = 1; $i <= 3; $i++) { for ($j = 1; $j <= 3; $j++) { if ($j === 2) { break; // ออกจาก inner loop เท่านั้น } echo "($i,$j) "; }}// (1,1) (2,1) (3,1)
// break หลายระดับfor ($i = 1; $i <= 3; $i++) { for ($j = 1; $j <= 3; $j++) { if ($i === 2 && $j === 2) { break 2; // ออกจาก 2 loops } echo "($i,$j) "; }}// (1,1) (1,2) (1,3) (2,1)
// break กับ switch (สำคัญ!)foreach ($items as $item) { switch ($item) { case "stop": break 2; // ออกจาก foreach ไม่ใช่ switch! default: echo $item; }}continue
Section titled “continue”ใช้ข้ามไปยังรอบถัดไป:
<?php// ข้ามเลขคู่for ($i = 1; $i <= 10; $i++) { if ($i % 2 === 0) { continue; // ข้ามเลขคู่ } echo $i . " "; // 1 3 5 7 9}
// ข้ามค่าว่าง$names = ["Alice", "", "Bob", null, "Charlie"];foreach ($names as $name) { if (empty($name)) { continue; } echo "$name\n";}// Alice// Bob// Charlie
// continue หลายระดับfor ($i = 1; $i <= 3; $i++) { for ($j = 1; $j <= 3; $j++) { if ($j === 2) { continue 2; // ข้ามไปรอบถัดไปของ outer loop } echo "($i,$j) "; }}// (1,1) (2,1) (3,1)ข้ามไปยัง label (ใช้น้อยมาก):
<?php// goto - ไม่แนะนำfor ($i = 0; $i < 10; $i++) { for ($j = 0; $j < 10; $j++) { if ($i * $j >= 25) { goto end; } echo "$i * $j = " . ($i * $j) . "\n"; }}end:echo "Done!";
// ❌ ไม่สามารถ goto เข้าไปใน loop ได้// goto inside;// for ($i = 0; $i < 5; $i++) {// inside: // Error!// echo $i;// }หลีกเลี่ยง goto
goto ทำให้โค้ดอ่านยากและ debug ยาก ใช้ break พร้อมระบุระดับแทน หรือ restructure โค้ดให้ไม่ต้องใช้
Loop กับ Iterators
Section titled “Loop กับ Iterators”PHP รองรับ Iterator pattern:
<?php// Generatorsfunction range_generator(int $start, int $end) { for ($i = $start; $i <= $end; $i++) { yield $i; }}
foreach (range_generator(1, 5) as $num) { echo $num . " "; // 1 2 3 4 5}
// Generator กับ key => valuefunction items_generator() { yield "a" => 1; yield "b" => 2; yield "c" => 3;}
foreach (items_generator() as $key => $value) { echo "$key: $value\n";}
// DirectoryIterator$dir = new DirectoryIterator("./");foreach ($dir as $file) { if ($file->isFile()) { echo $file->getFilename() . "\n"; }}
// ArrayIterator$iterator = new ArrayIterator(["a", "b", "c"]);foreach ($iterator as $value) { echo $value . " ";}Array Functions แทน Loop
Section titled “Array Functions แทน Loop”บ่อยครั้งใช้ array functions แทน loop ได้:
<?php$numbers = [1, 2, 3, 4, 5];
// แทน for loop ที่ transform ข้อมูล// ❌ Loop$doubled = [];foreach ($numbers as $n) { $doubled[] = $n * 2;}
// ✅ array_map$doubled = array_map(fn($n) => $n * 2, $numbers);// [2, 4, 6, 8, 10]
// แทน for loop ที่ filter// ❌ Loop$evens = [];foreach ($numbers as $n) { if ($n % 2 === 0) { $evens[] = $n; }}
// ✅ array_filter$evens = array_filter($numbers, fn($n) => $n % 2 === 0);// [2, 4]
// แทน for loop ที่ reduce// ❌ Loop$sum = 0;foreach ($numbers as $n) { $sum += $n;}
// ✅ array_reduce$sum = array_reduce($numbers, fn($acc, $n) => $acc + $n, 0);// 15
// หรือใช้ array_sum$sum = array_sum($numbers);// 15
// รวม map + filter$result = array_filter( array_map(fn($n) => $n * 2, $numbers), fn($n) => $n > 4);// [6, 8, 10]ข้อดีของ Array Functions
Section titled “ข้อดีของ Array Functions”- Declarative - บอกว่าทำอะไร ไม่ใช่ทำยังไง
- No mutation - สร้าง array ใหม่ ไม่แก้ของเดิม
- Chainable - ต่อกันได้
- Testable - test ง่ายกว่า
Common Loop Patterns
Section titled “Common Loop Patterns”Sum และ Average
Section titled “Sum และ Average”<?php$scores = [85, 92, 78, 95, 88];
// วิธี loop$sum = 0;foreach ($scores as $score) { $sum += $score;}$average = $sum / count($scores);
// วิธี function$sum = array_sum($scores);$average = $sum / count($scores);
echo "Sum: $sum, Average: $average";// Sum: 438, Average: 87.6Find First Match
Section titled “Find First Match”<?php$users = [ ["id" => 1, "name" => "Alice", "active" => true], ["id" => 2, "name" => "Bob", "active" => false], ["id" => 3, "name" => "Charlie", "active" => true],];
// หา user ที่ active = false คนแรก$found = null;foreach ($users as $user) { if (!$user["active"]) { $found = $user; break; // หาเจอแล้ว ออก }}
// หรือใช้ array_filter + reset$inactive = array_filter($users, fn($u) => !$u["active"]);$found = reset($inactive) ?: null;
echo $found["name"]; // "Bob"Group By
Section titled “Group By”<?php$products = [ ["name" => "iPhone", "category" => "phone"], ["name" => "Galaxy", "category" => "phone"], ["name" => "MacBook", "category" => "laptop"], ["name" => "XPS", "category" => "laptop"],];
// Group by category$grouped = [];foreach ($products as $product) { $category = $product["category"]; $grouped[$category][] = $product;}
print_r($grouped);// [// "phone" => [["name" => "iPhone", ...], ["name" => "Galaxy", ...]],// "laptop" => [["name" => "MacBook", ...], ["name" => "XPS", ...]]// ]Pagination
Section titled “Pagination”<?php$items = range(1, 100); // 1-100$page = 3;$perPage = 10;
// หา offset$offset = ($page - 1) * $perPage;
// ตัด array$pageItems = array_slice($items, $offset, $perPage);// [21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
// คำนวณจำนวนหน้า$totalPages = ceil(count($items) / $perPage);// 10Performance Tips
Section titled “Performance Tips”<?php// 1. Cache array length// ❌ Slowfor ($i = 0; $i < count($array); $i++) { }
// ✅ Fast$count = count($array);for ($i = 0; $i < $count; $i++) { }
// 2. ใช้ foreach แทน for index// ❌ Slowerfor ($i = 0; $i < count($array); $i++) { echo $array[$i];}
// ✅ Fasterforeach ($array as $item) { echo $item;}
// 3. หลีกเลี่ยง function call ใน loop// ❌ Slowforeach ($items as $item) { $result = someExpensiveFunction($item); // เรียกทุกรอบ}
// ✅ Fast (ถ้า memoize ได้)$cache = [];foreach ($items as $item) { $key = getKey($item); if (!isset($cache[$key])) { $cache[$key] = someExpensiveFunction($item); } $result = $cache[$key];}
// 4. ใช้ break เมื่อเจอแล้วforeach ($items as $item) { if ($item === $target) { $found = $item; break; // ไม่ต้อง loop ต่อ }}แบบฝึกหัด
Section titled “แบบฝึกหัด”แบบฝึกหัดที่ 1: FizzBuzz
Section titled “แบบฝึกหัดที่ 1: FizzBuzz”<?phpfunction fizzBuzz(int $n): void { for ($i = 1; $i <= $n; $i++) { $output = match(true) { $i % 15 === 0 => "FizzBuzz", $i % 3 === 0 => "Fizz", $i % 5 === 0 => "Buzz", default => (string) $i, }; echo "$output\n"; }}
fizzBuzz(15);แบบฝึกหัดที่ 2: Prime Numbers
Section titled “แบบฝึกหัดที่ 2: Prime Numbers”<?phpfunction isPrime(int $n): bool { if ($n < 2) return false; if ($n === 2) return true; if ($n % 2 === 0) return false;
for ($i = 3; $i <= sqrt($n); $i += 2) { if ($n % $i === 0) { return false; } } return true;}
function getPrimes(int $limit): array { $primes = []; for ($i = 2; $i <= $limit; $i++) { if (isPrime($i)) { $primes[] = $i; } } return $primes;}
print_r(getPrimes(50));// [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]แบบฝึกหัดที่ 3: Flatten Array
Section titled “แบบฝึกหัดที่ 3: Flatten Array”<?phpfunction flatten(array $array): array { $result = []; foreach ($array as $item) { if (is_array($item)) { $result = [...$result, ...flatten($item)]; } else { $result[] = $item; } } return $result;}
$nested = [1, [2, 3], [[4, 5], 6], 7];print_r(flatten($nested));// [1, 2, 3, 4, 5, 6, 7]ในบทนี้เราได้เรียนรู้:
- for loop สำหรับรู้จำนวนรอบ
- while และ do-while สำหรับ loop จนกว่าเงื่อนไขจะเปลี่ยน
- foreach สำหรับ loop ผ่าน arrays และ iterables
- break, continue และ goto
- Generators และ Iterators
- Array functions ที่ใช้แทน loops
- Common patterns และ performance tips
Best Practices
Section titled “Best Practices”1. ใช้ foreach แทน for กับ arrays
Section titled “1. ใช้ foreach แทน for กับ arrays”<?php// แนะนำforeach ($items as $item) { process($item);}
// ไม่แนะนำfor ($i = 0; $i < count($items); $i++) { process($items[$i]);}2. หลีกเลี่ยง Infinite Loops
Section titled “2. หลีกเลี่ยง Infinite Loops”<?php// อันตราย: ไม่มีทางออก// while (true) { }
// ปลอดภัย: มี break condition$maxIterations = 1000;$i = 0;while (true) { if ($i++ >= $maxIterations) break; // do something}3. Unset Reference หลัง foreach
Section titled “3. Unset Reference หลัง foreach”<?phpforeach ($items as &$item) { $item = process($item);}unset($item); // สำคัญมาก!แหล่งข้อมูลเพิ่มเติม
Section titled “แหล่งข้อมูลเพิ่มเติม”เข้าสู่ระบบเพื่อดูเนื้อหาเต็ม
ยืนยันตัวตนด้วยบัญชี Google เพื่อปลดล็อกบทความทั้งหมด
Login with Google