循环
概述
循环允许您根据特定条件重复执行代码。PHP提供了几种类型的循环:for、while、do-while和foreach。本章涵盖所有循环类型,包括实际示例和最佳实践。
For 循环
基本 For 循环
php
<?php
// 基本 for 循环结构:for (初始化; 条件; 递增)
for ($i = 0; $i < 5; $i++) {
echo "迭代: $i\n";
}
// 输出:迭代: 0, 1, 2, 3, 4
// 倒数计数
for ($i = 10; $i >= 1; $i--) {
echo "$i ";
}
echo "发射!\n";
// 输出:10 9 8 7 6 5 4 3 2 1 发射!
// 不同的递增值
for ($i = 0; $i <= 20; $i += 5) {
echo "$i ";
}
// 输出:0 5 10 15 20
// 多个变量
for ($i = 0, $j = 10; $i < 5; $i++, $j--) {
echo "i: $i, j: $j\n";
}
?>数组的 For 循环
php
<?php
$fruits = ['apple', 'banana', 'orange', 'grape'];
// 数组的传统 for 循环
for ($i = 0; $i < count($fruits); $i++) {
echo "水果 $i: {$fruits[$i]}\n";
}
// 更高效 - 将计数存储在变量中
$fruitCount = count($fruits);
for ($i = 0; $i < $fruitCount; $i++) {
echo "水果 $i: {$fruits[$i]}\n";
}
// 反向迭代
for ($i = count($fruits) - 1; $i >= 0; $i--) {
echo "反向水果 $i: {$fruits[$i]}\n";
}
?>嵌套 For 循环
php
<?php
// 乘法表
echo "<table border='1'>";
for ($i = 1; $i <= 10; $i++) {
echo "<tr>";
for ($j = 1; $j <= 10; $j++) {
$product = $i * $j;
echo "<td>$product</td>";
}
echo "</tr>";
}
echo "</table>";
// 模式打印
for ($i = 1; $i <= 5; $i++) {
for ($j = 1; $j <= $i; $j++) {
echo "* ";
}
echo "\n";
}
// 输出:
// *
// * *
// * * *
// * * * *
// * * * * *
// 二维数组处理
$matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
for ($row = 0; $row < count($matrix); $row++) {
for ($col = 0; $col < count($matrix[$row]); $col++) {
echo $matrix[$row][$col] . " ";
}
echo "\n";
}
?>While Loop
Basic While Loop
php
<?php
// Basic while loop
$counter = 0;
while ($counter < 5) {
echo "Counter: $counter\n";
$counter++;
}
// Reading file line by line
$file = fopen('data.txt', 'r');
if ($file) {
while (($line = fgets($file)) !== false) {
echo "Line: " . trim($line) . "\n";
}
fclose($file);
}
// User input validation
$attempts = 0;
$maxAttempts = 3;
$validInput = false;
while (!$validInput && $attempts < $maxAttempts) {
$input = readline("Enter a number between 1 and 10: ");
if (is_numeric($input) && $input >= 1 && $input <= 10) {
$validInput = true;
echo "Valid input: $input\n";
} else {
$attempts++;
echo "Invalid input. Attempts remaining: " . ($maxAttempts - $attempts) . "\n";
}
}
if (!$validInput) {
echo "Maximum attempts reached.\n";
}
?>While Loop with Arrays
php
<?php
$numbers = [1, 2, 3, 4, 5];
$index = 0;
// Process array with while loop
while ($index < count($numbers)) {
echo "Number at index $index: {$numbers[$index]}\n";
$index++;
}
// Find first even number
$numbers = [1, 3, 7, 8, 9, 12];
$index = 0;
$found = false;
while ($index < count($numbers) && !$found) {
if ($numbers[$index] % 2 === 0) {
echo "First even number: {$numbers[$index]} at index $index\n";
$found = true;
}
$index++;
}
if (!$found) {
echo "No even numbers found\n";
}
?>Do-While Loop
Basic Do-While Loop
php
<?php
// Do-while executes at least once
$number = 10;
do {
echo "Number: $number\n";
$number--;
} while ($number > 5);
// Menu system example
do {
echo "\n--- Menu ---\n";
echo "1. View users\n";
echo "2. Add user\n";
echo "3. Delete user\n";
echo "4. Exit\n";
$choice = (int)readline("Enter your choice: ");
switch ($choice) {
case 1:
echo "Viewing users...\n";
break;
case 2:
echo "Adding user...\n";
break;
case 3:
echo "Deleting user...\n";
break;
case 4:
echo "Goodbye!\n";
break;
default:
echo "Invalid choice. Please try again.\n";
}
} while ($choice !== 4);
?>Input Validation with Do-While
php
<?php
// Password validation
do {
$password = readline("Enter password (min 8 chars, must contain number): ");
$isValid = strlen($password) >= 8 && preg_match('/\d/', $password);
if (!$isValid) {
echo "Password must be at least 8 characters and contain a number.\n";
}
} while (!$isValid);
echo "Password accepted!\n";
// Dice rolling game
$totalScore = 0;
$round = 1;
do {
echo "\n--- Round $round ---\n";
$dice1 = rand(1, 6);
$dice2 = rand(1, 6);
$roundScore = $dice1 + $dice2;
$totalScore += $roundScore;
echo "Rolled: $dice1 + $dice2 = $roundScore\n";
echo "Total score: $totalScore\n";
if ($totalScore >= 50) {
echo "You win! Final score: $totalScore\n";
break;
}
$continue = strtolower(readline("Roll again? (y/n): "));
$round++;
} while ($continue === 'y' || $continue === 'yes');
?>Foreach Loop
Basic Foreach
php
<?php
// Foreach with indexed arrays
$colors = ['red', 'green', 'blue', 'yellow'];
foreach ($colors as $color) {
echo "Color: $color\n";
}
// Foreach with index
foreach ($colors as $index => $color) {
echo "Color $index: $color\n";
}
// Foreach with associative arrays
$person = [
'name' => 'John Doe',
'age' => 30,
'city' => 'New York',
'email' => 'john@example.com'
];
foreach ($person as $key => $value) {
echo "$key: $value\n";
}
?>Foreach with References
php
<?php
$numbers = [1, 2, 3, 4, 5];
// Modify array elements using references
foreach ($numbers as &$number) {
$number *= 2; // Double each number
}
unset($number); // Important: unset reference after loop
print_r($numbers); // [2, 4, 6, 8, 10]
// Without references (creates copies)
$numbers = [1, 2, 3, 4, 5];
foreach ($numbers as $number) {
$number *= 2; // This won't modify the original array
}
print_r($numbers); // [1, 2, 3, 4, 5] - unchanged
// Practical example: updating user data
$users = [
['name' => 'John', 'active' => false],
['name' => 'Jane', 'active' => true],
['name' => 'Bob', 'active' => false]
];
foreach ($users as &$user) {
if (!$user['active']) {
$user['active'] = true;
$user['activated_at'] = date('Y-m-d H:i:s');
}
}
unset($user);
?>Multidimensional Arrays with Foreach
php
<?php
$products = [
[
'name' => 'Laptop',
'price' => 999.99,
'categories' => ['Electronics', 'Computers']
],
[
'name' => 'Book',
'price' => 19.99,
'categories' => ['Education', 'Literature']
],
[
'name' => 'Headphones',
'price' => 149.99,
'categories' => ['Electronics', 'Audio']
]
];
foreach ($products as $product) {
echo "Product: {$product['name']}\n";
echo "Price: $" . number_format($product['price'], 2) . "\n";
echo "Categories: ";
foreach ($product['categories'] as $category) {
echo "$category ";
}
echo "\n---\n";
}
// Calculate total value by category
$categoryTotals = [];
foreach ($products as $product) {
foreach ($product['categories'] as $category) {
if (!isset($categoryTotals[$category])) {
$categoryTotals[$category] = 0;
}
$categoryTotals[$category] += $product['price'];
}
}
foreach ($categoryTotals as $category => $total) {
echo "$category: $" . number_format($total, 2) . "\n";
}
?>Loop Control Statements
Break Statement
php
<?php
// Break out of loop
for ($i = 0; $i < 10; $i++) {
if ($i === 5) {
break; // Exit the loop when i equals 5
}
echo "$i ";
}
echo "\nLoop ended at $i\n";
// Break with nested loops
for ($i = 1; $i <= 3; $i++) {
echo "Outer loop: $i\n";
for ($j = 1; $j <= 5; $j++) {
if ($j === 3) {
break; // Only breaks inner loop
}
echo " Inner loop: $j\n";
}
}
// Break multiple levels
for ($i = 1; $i <= 3; $i++) {
for ($j = 1; $j <= 3; $j++) {
if ($i === 2 && $j === 2) {
break 2; // Break out of both loops
}
echo "i: $i, j: $j\n";
}
}
// Practical example: finding in array
$users = ['alice', 'bob', 'charlie', 'diana'];
$searchName = 'charlie';
$found = false;
foreach ($users as $index => $user) {
if ($user === $searchName) {
echo "Found $searchName at index $index\n";
$found = true;
break; // Stop searching once found
}
}
if (!$found) {
echo "$searchName not found\n";
}
?>Continue Statement
php
<?php
// Skip even numbers
for ($i = 1; $i <= 10; $i++) {
if ($i % 2 === 0) {
continue; // Skip the rest of this iteration
}
echo "$i "; // Only odd numbers will be printed
}
// Process valid data only
$data = [1, 'invalid', 3, null, 5, 'bad', 7];
foreach ($data as $item) {
if (!is_numeric($item)) {
continue; // Skip non-numeric items
}
$squared = $item * $item;
echo "$item squared is $squared\n";
}
// Continue with nested loops
for ($i = 1; $i <= 3; $i++) {
echo "Processing group $i:\n";
for ($j = 1; $j <= 5; $j++) {
if ($j === 3) {
continue; // Skip j = 3 in inner loop
}
echo " Item $j\n";
}
}
// Practical example: processing user input
$inputs = ['john@email.com', 'invalid-email', 'jane@email.com', '', 'bob@email.com'];
$validEmails = [];
foreach ($inputs as $input) {
// Skip empty inputs
if (empty($input)) {
continue;
}
// Skip invalid emails
if (!filter_var($input, FILTER_VALIDATE_EMAIL)) {
echo "Skipping invalid email: $input\n";
continue;
}
$validEmails[] = $input;
}
echo "Valid emails: " . implode(', ', $validEmails) . "\n";
?>Alternative Loop Syntax
Alternative Syntax for Templates
php
<?php $users = ['Alice', 'Bob', 'Charlie']; ?>
<!-- For loop alternative syntax -->
<?php for ($i = 0; $i < count($users); $i++): ?>
<p>User <?= $i + 1 ?>: <?= $users[$i] ?></p>
<?php endfor; ?>
<!-- While loop alternative syntax -->
<?php $counter = 0; ?>
<?php while ($counter < 3): ?>
<div>Counter: <?= $counter ?></div>
<?php $counter++; ?>
<?php endwhile; ?>
<!-- Foreach alternative syntax -->
<?php foreach ($users as $index => $user): ?>
<li><?= $index + 1 ?>. <?= htmlspecialchars($user) ?></li>
<?php endforeach; ?>
<!-- Conditional display with loops -->
<?php if (!empty($users)): ?>
<ul>
<?php foreach ($users as $user): ?>
<li><?= htmlspecialchars($user) ?></li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p>No users found.</p>
<?php endif; ?>Practical Examples
Data Processing
php
<?php
// CSV data processing
$csvData = [
['Name', 'Age', 'City', 'Salary'],
['John', '30', 'New York', '50000'],
['Jane', '25', 'Los Angeles', '45000'],
['Bob', '35', 'Chicago', '55000'],
['Alice', '28', 'Miami', '48000']
];
$totalSalary = 0;
$employeeCount = 0;
$cities = [];
// Skip header row
for ($i = 1; $i < count($csvData); $i++) {
$row = $csvData[$i];
$name = $row[0];
$age = (int)$row[1];
$city = $row[2];
$salary = (int)$row[3];
// Calculate totals
$totalSalary += $salary;
$employeeCount++;
// Track cities
if (!in_array($city, $cities)) {
$cities[] = $city;
}
// Display employee info
echo "Employee: $name, Age: $age, City: $city, Salary: $" . number_format($salary) . "\n";
}
$averageSalary = $employeeCount > 0 ? $totalSalary / $employeeCount : 0;
echo "\nSummary:\n";
echo "Total employees: $employeeCount\n";
echo "Average salary: $" . number_format($averageSalary) . "\n";
echo "Cities: " . implode(', ', $cities) . "\n";
?>Form Processing
php
<?php
// Process multiple form submissions
$submissions = [
['name' => 'John', 'email' => 'john@email.com', 'age' => '25'],
['name' => '', 'email' => 'invalid-email', 'age' => 'abc'],
['name' => 'Jane', 'email' => 'jane@email.com', 'age' => '30'],
['name' => 'Bob', 'email' => 'bob@email.com', 'age' => '17']
];
$validSubmissions = [];
$errors = [];
foreach ($submissions as $index => $submission) {
$submissionErrors = [];
// Validate name
if (empty($submission['name'])) {
$submissionErrors[] = 'Name is required';
}
// Validate email
if (empty($submission['email'])) {
$submissionErrors[] = 'Email is required';
} elseif (!filter_var($submission['email'], FILTER_VALIDATE_EMAIL)) {
$submissionErrors[] = 'Invalid email format';
}
// Validate age
if (!is_numeric($submission['age'])) {
$submissionErrors[] = 'Age must be a number';
} elseif ($submission['age'] < 18) {
$submissionErrors[] = 'Must be at least 18 years old';
}
if (empty($submissionErrors)) {
$validSubmissions[] = $submission;
echo "Submission " . ($index + 1) . " is valid\n";
} else {
$errors[$index] = $submissionErrors;
echo "Submission " . ($index + 1) . " has errors:\n";
foreach ($submissionErrors as $error) {
echo " - $error\n";
}
}
}
echo "\nValid submissions: " . count($validSubmissions) . "\n";
echo "Invalid submissions: " . count($errors) . "\n";
?>File Processing
php
<?php
// Process log files
function processLogFile($filename) {
if (!file_exists($filename)) {
echo "File not found: $filename\n";
return;
}
$file = fopen($filename, 'r');
$lineNumber = 0;
$errorCount = 0;
$warningCount = 0;
while (($line = fgets($file)) !== false) {
$lineNumber++;
$line = trim($line);
// Skip empty lines
if (empty($line)) {
continue;
}
// Count different log levels
if (strpos($line, 'ERROR') !== false) {
$errorCount++;
echo "Line $lineNumber - ERROR: $line\n";
} elseif (strpos($line, 'WARNING') !== false) {
$warningCount++;
echo "Line $lineNumber - WARNING: $line\n";
}
// Stop if too many errors
if ($errorCount > 10) {
echo "Too many errors, stopping processing\n";
break;
}
}
fclose($file);
echo "\nSummary:\n";
echo "Total lines processed: $lineNumber\n";
echo "Errors found: $errorCount\n";
echo "Warnings found: $warningCount\n";
}
// Usage
// processLogFile('application.log');
?>Database-like Operations
php
<?php
// Simulate database operations with arrays
$users = [
['id' => 1, 'name' => 'John', 'email' => 'john@email.com', 'active' => true],
['id' => 2, 'name' => 'Jane', 'email' => 'jane@email.com', 'active' => false],
['id' => 3, 'name' => 'Bob', 'email' => 'bob@email.com', 'active' => true],
['id' => 4, 'name' => 'Alice', 'email' => 'alice@email.com', 'active' => true]
];
// Find user by ID
function findUserById($users, $id) {
foreach ($users as $user) {
if ($user['id'] === $id) {
return $user;
}
}
return null;
}
// Get active users
function getActiveUsers($users) {
$activeUsers = [];
foreach ($users as $user) {
if ($user['active']) {
$activeUsers[] = $user;
}
}
return $activeUsers;
}
// Update user status
function updateUserStatus(&$users, $id, $active) {
foreach ($users as &$user) {
if ($user['id'] === $id) {
$user['active'] = $active;
return true;
}
}
return false;
}
// Usage examples
$user = findUserById($users, 2);
if ($user) {
echo "Found user: {$user['name']}\n";
}
$activeUsers = getActiveUsers($users);
echo "Active users: " . count($activeUsers) . "\n";
updateUserStatus($users, 2, true);
echo "Updated user status\n";
?>Performance Considerations
Loop Optimization
php
<?php
$largeArray = range(1, 100000);
// Inefficient - count() called every iteration
$start = microtime(true);
for ($i = 0; $i < count($largeArray); $i++) {
// Process item
}
$time1 = microtime(true) - $start;
// Efficient - count() called once
$start = microtime(true);
$arrayCount = count($largeArray);
for ($i = 0; $i < $arrayCount; $i++) {
// Process item
}
$time2 = microtime(true) - $start;
echo "Inefficient loop: " . number_format($time1, 4) . " seconds\n";
echo "Efficient loop: " . number_format($time2, 4) . " seconds\n";
// Use foreach for arrays when possible (usually faster)
$start = microtime(true);
foreach ($largeArray as $item) {
// Process item
}
$time3 = microtime(true) - $start;
echo "Foreach loop: " . number_format($time3, 4) . " seconds\n";
?>Next Steps
Now that you understand loops, let's explore functions in Functions.
Practice Exercises
- Create a multiplication table generator using nested for loops
- Build a number guessing game using while loops
- Process a CSV file using foreach loops
- Implement a simple search function with break and continue
- Create a menu-driven program using do-while loops
Mastering loops is essential for processing data and creating interactive PHP applications!