流程控制:循环语句

一个完整的脚本程序应该由一系列语句构成。一条语句也许是一个赋值语句、一个条件判断、一个循环、一个函数调用、或者是什么也不做的空语句。语句通常使用分号结束,并且多个语句可使用花括号进行分组,当做一行语句。

在之前的章节中我们已经学习了赋值语句,这章我们学习 PHP 的流程控制

流程控制包括条件判断(ifelseelseif/else ifswitch)、循环(whiledo-whileforforeach)和中止循环(breakcontinuereturn)等。

上一节我们学习了条件判断语句,下面我们来看看循环语句


在开发过程中经常会遇到需要反复运行同一代码块的情况,例如从数据库中调取了一组数据后需要将之以某种格式输出到屏幕上,如果对每个数据进行单独的输出操作,那就太累了,也不是好的开发实践。那么此时我们就可以使用循环。

循环语句有以下几种:

  • while:只要条件为真,就循环执行代码块,直到条件不为真
  • do-while:不论条件是否为真,先执行一次代码,再根据条件真假循环执行代码块
  • for:PHP中最复杂的循环结构,循环执行指定的次数,或者当指定条件为真时循环执行代码块
  • foreach:仅用于数组和对象的遍历

先从while开始!

while

while是 PHP 最简单的循环结构,while先检查条件是否成立,成立则循环代码块。语法如下,其中expression为判断循环继续的条件:

while(expression)
    // 循环代码块

一个简单的示例代码:

<?php

// while

$val = 1;
while ($val < 100) {
    echo $val,' ';
    $val++;// 循环中止条件
}// 输出从1到99之间所有的数字

do...while

do...whilewhile很像,但是do...while会先不管不顾地执行一次代码,之后再检查条件,根据条件进行循环。语法如下,其中expression为判断循环继续的条件:

do {
    // 循环代码块
} while(expression);

一个简单的示例:

<?php

// do-while

$val = 1;
do {
    echo $val , ' ';
    $val++;
} while($val < 100);

上例同样输出 1 到 99 之间的整数,好像与while循环没有区别。那可以看看下面这个例子:

<?php

// 输出:100
$val = 100;
do {
    echo $val , ' ';
    $val++;
} while($val < 100);

// 无输出
$val = 100;
while ($val < 100) {
    echo $val , ' ';
    $val++;
}

由以上代码可看出,相比于while循环,do...while适用于至少执行一次的循环。其余情况二者可以互相转化。

for

for循环用于已知循环次数的情况。语法如下:

for(expression1; expression2; expression3) {
    // 循环代码块
}

其中expression1expression2expression3都是表达式。第一个表达式在循环前无条件求值(并执行)一次,通常用来定义初始值;第二个表达式则为循环条件,每次循环前如果该值为真,则继续循环;第三个表达式是每次循环后执行。三个表达式都可以为空,也可以是用逗号隔开的多个表达式,但是由于第二个表达式的特殊性(循环判断条件),第二个表达式为空时可能陷入死循环(如果循环代码块中没有带条件的结束语句的话)。

因为for循环的三个表达式可自定义,增加了for循环的复杂性(也被称为PHP中最复杂的循环结构)。这里仅作简单讲解,后续将逐渐深入for循环的使用。

一个简单的示例:

<?php

// for

for ($i = 1; $i < 100; $i++) { 
    echo $i,' ';
}// 输出1-99之间的整数

echo PHP_EOL;

// 第二个表达式为空时(未设置循环条件)
for ($i = 1; ; $i++) { 
    if($i > 99)
        break;// 循环体内设置有条件的终止语句来跳出循环
    echo $i,' ';
}// 输出1-99之间的整数

foreach

foreach仅用于数组与对象的遍历,如果尝试应用于其他数据类型或者未初始化的变量,将会报错。语法结构如下:

foreach ($variable as $key => $value) {
    ## 循环体
}

foreach ($variable as $value) {
    ## 循环体
}

foreach有两种写法,第一种是遍历变量$variable的所有值键对($key为数组元素的键名/对象的公开属性名,$value为相应的数组元素的值/对象的公开属性值),第二种是只遍历变量$variable的值。

请看下面简单示例:

<?php

// foreach

$arr = [
    'host'=>'https://www.jisuapi.com/',
    'name'=>'极速数据',
    'profile'=>'极速数据平台提供各类生活数据API,方便开发者快速简单的开发APP、软件及其他服务平台。公交、火车、违章、快递等数据应有尽有。',
    'address'=>'浙江省杭州市',
];// 数组

foreach ($arr as $key => $value) {
    echo $key , ': ', $value, PHP_EOL;
}
/* 输出:
host: https://www.jisuapi.com/
name: 极速数据
profile: 极速数据平台提供各类生活数据API,方便开发者快速简单的开发APP、软件及其他服务平台。公交、火车、违章、快递等数据应有尽有。
address: 浙江省杭州市
*/

class Site
{
    public $host = 'https://www.jisuapi.com/';
    public $name = '极速数据';
    public $profile = '极速数据平台提供各类生活数据API,方便开发者快速简单的开发APP、软件及其他服务平台。公交、火车、违章、快递等数据应有尽有。';
    public $address = '浙江省杭州市';

    private $admin = 'Liu';// 私有属性,foreach遍历不可见
    protected $statu = true;// 受保护属性,foreach遍历不可见
}
$obj = new Site();// 对象
foreach ($obj as $key => $value) {
    echo $key , ': ', $value, PHP_EOL;// 仅可遍历对象的可见属性
}
/* 输出:
host: https://www.jisuapi.com/
name: 极速数据
profile: 极速数据平台提供各类生活数据API,方便开发者快速简单的开发APP、软件及其他服务平台。公交、火车、违章、快递等数据应有尽有。
address: 浙江省杭州市
*/

foreach开始循环时,数组内部的指针自动指向第一个数组单元,每次循环时,数组内部指针都会向前移一步(所以在下一次循环时可以得到下一个数组元素)。这同时造成了foreach内部数组指针的依赖,在循环体内进行一些修改元素、删除元素的值时可能会导致意料之外的错误。


关于流程控制中的循环就先到这里,之后在项目中遇到的各种复杂循环也会通过案例来逐个解决。好的,下一节我们开始学习流程控制中的中止语句