Skip to content

循环

概述

循环允许您根据特定条件重复执行代码。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

  1. Create a multiplication table generator using nested for loops
  2. Build a number guessing game using while loops
  3. Process a CSV file using foreach loops
  4. Implement a simple search function with break and continue
  5. Create a menu-driven program using do-while loops

Mastering loops is essential for processing data and creating interactive PHP applications!

本站内容仅供学习和研究使用。