PHP For循环

For循环是PHP中最常用的循环结构之一,特别适合于已知循环次数的情况。本教程将详细介绍PHP中For循环的语法、用法、技巧和实际应用场景,帮助您掌握这种强大的循环控制结构。

For循环概述

For循环是一种预测试循环,它在执行循环体之前先检查条件。与While循环相比,For循环将初始化、条件判断和循环变量更新合并到一个语句中,使代码更加简洁清晰,特别适合于需要精确控制循环次数的场景。

For循环的语法

for (初始化; 条件; 更新) {
    // 要重复执行的代码块
}

For循环的三个表达式分别表示:

  1. 初始化:在循环开始前执行一次,用于初始化循环变量
  2. 条件:每次循环开始前进行判断,如果条件为真(TRUE),则执行循环体;如果条件为假(FALSE),则退出循环
  3. 更新:每次循环体执行完后进行,用于更新循环变量

For循环的工作原理

  1. 执行初始化表达式,通常用于设置循环变量的初始值
  2. 计算条件表达式的值,如果条件为真(TRUE),则执行循环体;如果条件为假(FALSE),则循环结束
  3. 执行完循环体后,执行更新表达式,通常用于递增或递减循环变量
  4. 返回步骤2,继续下一轮循环

For循环的基本示例

打印数字序列

<?php
// 打印1到10的数字
for ($i = 1; $i <= 10; $i++) {
    echo $i . " ";
}// 输出: 1 2 3 4 5 6 7 8 9 10
?>

在这个例子中:

  • $i = 1:初始化循环变量$i为1
  • $i <= 10:循环条件,当$i小于或等于10时,循环继续
  • $i++:每次循环结束后,$i的值增加1

倒计时

<?php
// 打印10到1的倒计时
for ($i = 10; $i >= 1; $i--) {
    echo $i . " ";
}echo "开始!";
// 输出: 10 9 8 7 6 5 4 3 2 1 开始!
?>

在这个例子中,我们使用递减运算符(--)来创建一个倒计时效果。

计算数字和

<?php
// 计算1到100的和
$sum = 0;
for ($i = 1; $i <= 100; $i++) {
    $sum += $i;
}
echo "1到100的和是: " . $sum;
// 输出: 1到100的和是: 5050
?>

这个例子展示了如何使用For循环来计算一系列数字的和。

For循环的变体

省略初始化表达式

<?php
// 省略初始化表达式(在循环外部初始化)
$i = 1;
for (; $i <= 10; $i++) {
    echo $i . " ";
}// 输出: 1 2 3 4 5 6 7 8 9 10
?>

省略条件表达式

<?php
// 省略条件表达式(创建无限循环,但在循环体内使用break退出)
for ($i = 1; ; $i++) {
    echo $i . " ";
    if ($i == 10) {
        break;
    }
}// 输出: 1 2 3 4 5 6 7 8 9 10
?>

省略更新表达式

<?php
// 省略更新表达式(在循环体内更新)
for ($i = 1; $i <= 10; ) {
    echo $i . " ";
    $i++;
}// 输出: 1 2 3 4 5 6 7 8 9 10
?>

省略所有表达式

<?php
// 省略所有表达式(创建无限循环,但在循环体内使用break退出)
$i = 1;
for (;;) {
    echo $i . " ";
    $i++;
    if ($i > 10) {
        break;
    }
}// 输出: 1 2 3 4 5 6 7 8 9 10
?>

多个循环变量

<?php
// 使用多个循环变量
for ($i = 1, $j = 10; $i <= 10; $i++, $j--) {
    echo "$i 和 $j ";
}// 输出: 1 和 10 2 和 9 3 和 8 4 和 7 5 和 6 6 和 5 7 和 4 8 和 3 9 和 2 10 和 1
?>

在这个例子中,我们同时使用了两个循环变量$i和$j,它们分别递增和递减。

使用For循环遍历数组

遍历索引数组

<?php
// 创建一个索引数组
$fruits = array("苹果", "香蕉", "橙子", "葡萄", "草莓");

// 使用for循环遍历索引数组
for ($i = 0; $i < count($fruits); $i++) {
    echo "索引$i: " . $fruits[$i] . "<br>";
}
?>

优化的数组遍历(将count()移到循环外部)

<?php
// 创建一个索引数组
$fruits = array("苹果", "香蕉", "橙子", "葡萄", "草莓");

// 获取数组长度(将count()移到循环外部以提高性能)
$length = count($fruits);

// 使用优化的for循环遍历索引数组
for ($i = 0; $i < $length; $i++) {
    echo "索引$i: " . $fruits[$i] . "<br>";
}
?>

将count()函数移到循环外部可以避免在每次循环迭代时都重新计算数组长度,提高代码性能,特别是对于大型数组。

遍历关联数组

<?php
// 创建一个关联数组
$person = array(
    "name" => "张三",
    "age" => 30,
    "job" => "工程师",
    "city" => "北京"
);

// 获取关联数组的键和值
$keys = array_keys($person);
$values = array_values($person);
$length = count($keys);

// 使用for循环遍历关联数组
for ($i = 0; $i < $length; $i++) {
    echo "$keys[$i]: $values[$i]<br>";
}
?>

对于关联数组,我们可以先使用array_keys()和array_values()函数获取键和值的数组,然后再使用For循环遍历。

嵌套For循环

嵌套For循环是指在一个For循环内部包含另一个或多个For循环。嵌套循环常用于处理二维数组或生成表格等需要多层迭代的场景。

打印乘法表

<?php
// 使用嵌套for循环打印乘法表
for ($i = 1; $i <= 9; $i++) {
    for ($j = 1; $j <= $i; $j++) {
        echo "$j × $i = " . ($j * $i) . "\t";
    }
    echo "<br>";
}
?>

生成二维数组

<?php
// 使用嵌套for循环生成一个3×3的二维数组
$matrix = array();

for ($i = 0; $i < 3; $i++) {
    for ($j = 0; $j < 3; $j++) {
        $matrix[$i][$j] = $i * 3 + $j + 1;
    }
}

// 打印二维数组
for ($i = 0; $i < 3; $i++) {
    for ($j = 0; $j < 3; $j++) {
        echo $matrix[$i][$j] . " ";
    }
    echo "<br>";
}
// 输出:
// 1 2 3 
// 4 5 6 
// 7 8 9 
?>

在For循环中使用break和continue

使用break跳出循环

<?php
// 使用break语句跳出循环
for ($i = 1; $i <= 100; $i++) {
    echo $i . " ";
    
    // 当$i等于20时跳出循环
    if ($i == 20) {
        break;
    }
}// 输出: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
?>

在嵌套循环中使用带标签的break

<?php
// 在嵌套循环中使用带标签的break语句
outer: // 外部循环标签
for ($i = 1; $i <= 5; $i++) {
    for ($j = 1; $j <= 5; $j++) {
        echo "($i, $j) ";
        
        // 当$i和$j都等于3时,跳出外部循环
        if ($i == 3 && $j == 3) {
            break outer; // 跳出带outer标签的循环
        }
    }
    echo "<br>";
}// 输出: (1, 1) (1, 2) (1, 3) (1, 4) (1, 5) 
// (2, 1) (2, 2) (2, 3) (2, 4) (2, 5) 
// (3, 1) (3, 2) (3, 3) 
?>

使用continue跳过当前迭代

<?php
// 使用continue语句跳过偶数
for ($i = 1; $i <= 10; $i++) {
    // 如果$i是偶数,跳过当前迭代
    if ($i % 2 == 0) {
        continue;
    }
    
    echo $i . " ";
}// 输出: 1 3 5 7 9
?>

在嵌套循环中使用带标签的continue

<?php
// 在嵌套循环中使用带标签的continue语句
outer: // 外部循环标签
for ($i = 1; $i <= 5; $i++) {
    for ($j = 1; $j <= 5; $j++) {
        // 当$j等于3时,跳过外部循环的当前迭代
        if ($j == 3) {
            continue outer; // 跳到outer标签的下一次迭代
        }
        echo "($i, $j) ";
    }
    echo "<br>";
}// 输出: (1, 1) (1, 2) (2, 1) (2, 2) (3, 1) (3, 2) (4, 1) (4, 2) (5, 1) (5, 2)
?>

PHP For循环的最佳实践

  1. 明确循环目的:在使用For循环之前,明确循环的目的和要解决的问题。
  2. 避免无限循环:确保循环条件最终会变为假,否则循环将无限执行下去。
  3. 优化循环性能:将循环中不变的计算移到循环外部,减少循环内部的计算量。
  4. 选择合适的循环类型:根据具体需求选择合适的循环类型。For循环适合已知循环次数的场景;While循环适合条件控制的循环;Foreach循环适合遍历数组。
  5. 保持循环体简洁:尽量保持循环体简洁明了,如果循环体过于复杂,可以考虑将部分代码提取到函数中。
  6. 避免修改循环变量:除非必要,否则不要在循环体中修改循环变量,这可能导致循环行为变得难以预测。
  7. 使用适当的缩进和格式:正确的缩进和格式可以使循环结构更加清晰易懂,便于阅读和维护。
  8. 注释复杂循环:对于复杂的循环,添加注释说明循环的目的和工作原理。

PHP For循环综合示例

<?php
// 1. 简单的计数器

echo "<h4>1. 简单的计数器</h4>";

// 使用for循环从1数到10
for ($i = 1; $i <= 10; $i++) {
    echo "计数: " . $i . "<br>";
}

// 2. 计算阶乘

echo "<h4>2. 计算阶乘</h4>";

function calculate_factorial($n) {
    // 检查输入是否有效
    if (!is_int($n) || $n < 0) {
        return "无效输入:请输入非负整数";
    }
    
    // 特殊情况:0的阶乘是1
    if ($n == 0) {
        return 1;
    }
    
    // 使用for循环计算阶乘
    $result = 1;
    for ($i = 1; $i <= $n; $i++) {
        $result *= $i;
    }
    
    return $result;
}

// 测试阶乘函数
$number = 6;
echo "$number 的阶乘是: " . calculate_factorial($number) . "<br>";
// 输出: 6 的阶乘是: 720

// 3. 生成斐波那契数列

echo "<h4>3. 生成斐波那契数列</h4>";

function generate_fibonacci($n) {
    // 检查输入是否有效
    if (!is_int($n) || $n <= 0) {
        return "无效输入:请输入正整数";
    }
    
    // 处理特殊情况
    if ($n == 1) {
        return array(0);
    }
    
    // 初始化斐波那契数列
    $fibonacci = array(0, 1);
    
    // 使用for循环生成斐波那契数列
    for ($i = 2; $i < $n; $i++) {
        $fibonacci[] = $fibonacci[$i-1] + $fibonacci[$i-2];
    }
    
    return $fibonacci;
}

// 生成前15个斐波那契数
$fibonacci_sequence = generate_fibonacci(15);
echo "前15个斐波那契数: " . implode(", ", $fibonacci_sequence) . "<br>";
// 输出: 前15个斐波那契数: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377

// 4. 遍历并处理数组

echo "<h4>4. 遍历并处理数组</h4>";

// 创建一个数字数组
$numbers = array(5, 2, 9, 1, 5, 6, 3, 8, 4, 7);
echo "原始数组: " . implode(", ", $numbers) . "<br>";

// 找出最大值
$max_value = $numbers[0];
for ($i = 1; $i < count($numbers); $i++) {
    if ($numbers[$i] > $max_value) {
        $max_value = $numbers[$i];
    }
}
echo "数组中的最大值: " . $max_value . "<br>";

// 计算平均值
$sum = 0;
for ($i = 0; $i < count($numbers); $i++) {
    $sum += $numbers[$i];
}
$average = $sum / count($numbers);
echo "数组的平均值: " . $average . "<br>";

// 排序数组(使用冒泡排序算法)
$length = count($numbers);
for ($i = 0; $i < $length - 1; $i++) {
    for ($j = 0; $j < $length - $i - 1; $j++) {
        if ($numbers[$j] > $numbers[$j+1]) {
            // 交换元素
            $temp = $numbers[$j];
            $numbers[$j] = $numbers[$j+1];
            $numbers[$j+1] = $temp;
        }
    }
}
echo "排序后的数组: " . implode(", ", $numbers) . "<br>";

// 5. 生成HTML表格

echo "<h4>5. 生成HTML表格</h4>";

function generate_table($rows, $cols) {
    // 检查输入是否有效
    if (!is_int($rows) || !is_int($cols) || $rows <= 0 || $cols <= 0) {
        return "无效输入:请输入正整数";
    }
    
    // 开始表格
    $table = "<table border='1' cellspacing='0' cellpadding='5'>";
    
    // 使用for循环生成表头
    $table .= "<tr><th>单元格</th>";
    for ($j = 1; $j <= $cols; $j++) {
        $table .= "<th>列 $j</th>";
    }
    $table .= "</tr>";
    
    // 使用嵌套for循环生成表格内容
    for ($i = 1; $i <= $rows; $i++) {
        $table .= "<tr><th>行 $i</th>";
        
        for ($j = 1; $j <= $cols; $j++) {
            $table .= "<td>行$i, 列$j</td>";
        }
        
        $table .= "</tr>";
    }
    
    // 结束表格
    $table .= "</table>";
    
    return $table;
}

// 生成一个4x5的表格
echo generate_table(4, 5);

// 6. 简单的分页显示

echo "<h4>6. 简单的分页显示</h4>";

// 模拟数据
$items_per_page = 6;
$total_items = 35;
$total_pages = ceil($total_items / $items_per_page);

// 获取当前页码
$current_page = isset($_GET['page']) ? intval($_GET['page']) : 1;
$current_page = max(1, min($current_page, $total_pages));

// 计算当前页的起始项和结束项
$start_item = ($current_page - 1) * $items_per_page + 1;
$end_item = min($current_page * $items_per_page, $total_items);

// 显示当前页的内容
$i = $start_item;
echo "第 $current_page 页 (共 $total_pages 页): <br>";
echo "显示第 $start_item 到 $end_item 项 (共 $total_items 项): <br>";
echo "<ul>";

for (; $i <= $end_item; $i++) {
    echo "<li>项目 $i</li>";
}
echo "</ul>";

// 显示分页链接
echo "<div class='pagination'>";

// 显示上一页链接
if ($current_page > 1) {
    echo "<a href='?page=" . ($current_page - 1) . "'>上一页</a> ";
}

// 显示页码链接
$page_range = 2; // 当前页前后显示的页数
$start_page = max(1, $current_page - $page_range);
$end_page = min($total_pages, $current_page + $page_range);

for ($i = $start_page; $i <= $end_page; $i++) {
    if ($i == $current_page) {
        echo "<span class='current-page'>$i</span> ";
    } else {
        echo "<a href='?page=$i'>$i</a> ";
    }
}

// 显示下一页链接
if ($current_page < $total_pages) {
    echo "<a href='?page=" . ($current_page + 1) . "'>下一页</a>";
}

echo "</div>";

// 7. 简单的计算器

echo "<h4>7. 简单的计算器</h4>";

// 处理计算器表单提交
if (isset($_POST['calculate'])) {
    $num1 = floatval($_POST['num1']);
    $num2 = floatval($_POST['num2']);
    $operation = $_POST['operation'];
    $result = 0;
    
    // 使用switch语句根据操作类型执行不同的计算
    switch ($operation) {
        case 'add':
            $result = $num1 + $num2;
            break;
        case 'subtract':
            $result = $num1 - $num2;
            break;
        case 'multiply':
            $result = $num1 * $num2;
            break;
        case 'divide':
            if ($num2 == 0) {
                echo "错误:除数不能为零!<br>";
            } else {
                $result = $num1 / $num2;
            }
            break;
        default:
            echo "错误:无效的操作!<br>";
    }
    
    if (isset($result)) {
        echo "计算结果: " . $result . "<br>";
    }
}

// 显示计算器表单
echo '<form method="post" action="' . htmlspecialchars($_SERVER['PHP_SELF']) . '">
    第一个数: <input type="number" name="num1" required><br>
    操作: 
    <select name="operation" required>
        <option value="add">+</option>
        <option value="subtract">-</option>
        <option value="multiply">*</option>
        <option value="divide">/</option>
    </select><br>
    第二个数: <input type="number" name="num2" required><br>
    <input type="submit" name="calculate" value="计算">
</form>';

// 8. 简单的用户输入验证

echo "<h4>8. 简单的用户输入验证</h4>";

// 模拟用户注册表单
if (isset($_POST['register'])) {
    $username = trim($_POST['username']);
    $email = trim($_POST['email']);
    $password = trim($_POST['password']);
    $confirm_password = trim($_POST['confirm_password']);
    
    $errors = array();
    
    // 验证用户名
    if (empty($username)) {
        $errors[] = "用户名不能为空";
    } else if (strlen($username) < 3) {
        $errors[] = "用户名至少需要3个字符";
    }
    
    // 验证电子邮件
    if (empty($email)) {
        $errors[] = "电子邮件不能为空";
    } else if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors[] = "请输入有效的电子邮件地址";
    }
    
    // 验证密码
    if (empty($password)) {
        $errors[] = "密码不能为空";
    } else if (strlen($password) < 6) {
        $errors[] = "密码至少需要6个字符";
    }
    
    // 验证确认密码
    if (empty($confirm_password)) {
        $errors[] = "请确认密码";
    } else if ($password !== $confirm_password) {
        $errors[] = "两次输入的密码不一致";
    }
    
    // 显示验证结果
    if (count($errors) > 0) {
        echo "<div class='error-messages'>";
        echo "请修复以下错误:<br>";
        for ($i = 0; $i < count($errors); $i++) {
            echo "- " . $errors[$i] . "<br>";
        }
        echo "</div>";
    } else {
        echo "<div class='success-message'>";
        echo "注册成功!<br>";
        echo "用户名: " . htmlspecialchars($username) . "<br>";
        echo "电子邮件: " . htmlspecialchars($email) . "<br>";
        echo "</div>";
    }
}

// 显示用户注册表单
echo '<form method="post" action="' . htmlspecialchars($_SERVER['PHP_SELF']) . '">
    用户名: <input type="text" name="username" value="' . (isset($_POST['username']) ? htmlspecialchars($_POST['username']) : '') . '"><br>
    电子邮件: <input type="email" name="email" value="' . (isset($_POST['email']) ? htmlspecialchars($_POST['email']) : '') . '"><br>
    密码: <input type="password" name="password"><br>
    确认密码: <input type="password" name="confirm_password"><br>
    <input type="submit" name="register" value="注册">
</form>';

// 9. 简单的投票系统

echo "<h4>9. 简单的投票系统</h4>";

session_start();

// 初始化投票选项
if (!isset($_SESSION['votes'])) {
    $_SESSION['votes'] = array(
        'option1' => 0,
        'option2' => 0,
        'option3' => 0
    );
}

// 初始化用户投票状态
if (!isset($_SESSION['has_voted'])) {
    $_SESSION['has_voted'] = false;
}

// 处理投票提交
if (isset($_POST['vote']) && !$_SESSION['has_voted']) {
    $selected_option = $_POST['option'];
    
    // 验证投票选项
    if (isset($_SESSION['votes'][$selected_option])) {
        $_SESSION['votes'][$selected_option]++;
        $_SESSION['has_voted'] = true;
        echo "投票成功!谢谢参与。<br>";
    } else {
        echo "无效的投票选项!<br>";
    }
} else if (isset($_POST['vote']) && $_SESSION['has_voted']) {
    echo "您已经投过票了!<br>";
}

// 显示投票结果
$total_votes = array_sum($_SESSION['votes']);
echo "投票结果: <br>";
echo "<ul>";

$options = array(
    'option1' => '选项1',
    'option2' => '选项2',
    'option3' => '选项3'
);

$option_keys = array_keys($options);
for ($i = 0; $i < count($option_keys); $i++) {
    $key = $option_keys[$i];
    $votes = $_SESSION['votes'][$key];
    $percentage = $total_votes > 0 ? round(($votes / $total_votes) * 100) : 0;
    
    echo "<li>" . $options[$key] . ": " . $votes . " 票 (" . $percentage . "%)</li>";
}

echo "</ul>";
echo "总票数: " . $total_votes . "<br><br>";

// 显示投票表单(如果用户还没有投票)
if (!$_SESSION['has_voted']) {
    echo '<form method="post" action="' . htmlspecialchars($_SERVER['PHP_SELF']) . '">
        请选择您的选项:<br>';
    
    for ($i = 0; $i < count($option_keys); $i++) {
        $key = $option_keys[$i];
        echo '<input type="radio" name="option" value="' . $key . '" id="' . $key . '">
        <label for="' . $key . '">' . $options[$key] . '</label><br>';
    }
    
    echo '<input type="submit" name="vote" value="投票">
</form>';
}

// 提供重置投票的选项(实际应用中应该有更严格的权限控制)
echo "<br><a href='?reset_votes'>重置投票</a>";

// 处理重置投票
if (isset($_GET['reset_votes'])) {
    $_SESSION['votes'] = array(
        'option1' => 0,
        'option2' => 0,
        'option3' => 0
    );
    $_SESSION['has_voted'] = false;
    echo "<br>投票已重置!<br>";
}

// 10. 生成日历

echo "<h4>10. 生成日历</h4>";

function generate_calendar($year, $month) {
    // 检查输入是否有效
    if (!is_int($year) || !is_int($month) || $month < 1 || $month > 12) {
        return "无效输入:请输入有效的年份和月份";
    }
    
    // 获取月份的第一天是星期几(0=星期日,1=星期一,...,6=星期六)
    $first_day = date('w', mktime(0, 0, 0, $month, 1, $year));
    
    // 获取月份的天数
    $days_in_month = date('t', mktime(0, 0, 0, $month, 1, $year));
    
    // 开始表格
    $calendar = "<table border='1' cellspacing='0' cellpadding='5'>";
    
    // 显示月份和年份
    $month_name = date('F', mktime(0, 0, 0, $month, 1, $year));
    $calendar .= "<caption>$month_name $year</caption>";
    
    // 显示星期标题
    $calendar .= "<tr><th>日</th><th>一</th><th>二</th><th>三</th><th>四</th><th>五</th><th>六</th></tr>";
    
    // 初始化日期计数器
    $day = 1;
    
    // 使用嵌套for循环生成日历
    for ($week = 0; $week < 6 && $day <= $days_in_month; $week++) {
        $calendar .= "<tr>";
        
        for ($dow = 0; $dow < 7; $dow++) {
            // 填充月份第一天之前的空白单元格
            if ($week == 0 && $dow < $first_day) {
                $calendar .= "<td>&nbsp;</td>";
            } else if ($day > $days_in_month) {
                // 填充月份最后一天之后的空白单元格
                $calendar .= "<td>&nbsp;</td>";
            } else {
                // 检查是否是今天
                $is_today = ($day == date('d') && $month == date('m') && $year == date('Y'));
                $calendar .= "<td" . ($is_today ? " class='today'" : "") . ">" . $day . "</td>";
                $day++;
            }
        }
        
        $calendar .= "</tr>";
    }
    
    // 结束表格
    $calendar .= "</table>";
    
    return $calendar;
}

// 生成当前月份的日历
echo generate_calendar(date('Y'), date('m'));
?>