流程控制允许你控制你编写的脚本流(Siemen注:通俗点说就是按照你的安排去执行程序)——毕竟,一个脚本从开始一直运行到结束,你没有控制其运行走向与运行多少次数,那么程序也不会知道下一步该怎么做。
PHP提供了一些与与众不同的流程控制——包括一些看似多余,确实对简化开发的。你应该要熟悉他们,把他们当作语言结构不可分割的部分。
条件控制结构是被用来改变一个或者多个脚本执行流向的。最最基础的结构就是if-then-else结构,能够决定执行两条语句中的哪个一条(或者把代码块插入到其中):
if (表达式1) { } elseif (表达式2) { // 提示:这里的elseif如果写成else if也是可以的 } else { }
在这里,如果“表达式1”为true,那么它下面的代码块中的代码会被立即执行。如果没有情况符合,解释器会试图执行else部分语句。需要提醒的是使用个连续的else if语句可以使用elseif来代替,他们是等价的。
那么if-then-else也可以被嵌套使用:
if (表达式1) { if (表达式2) { // 代码 } else { // 更多代码 } } else { if (表达式3) { // 更多代码 } }
有一个特殊的三元操作符允许你把if-then-else嵌入到一个表达式中去执行:
echo 10 == $x ? 'Yes' : 'No';
上面这行代码与下面这段代码效果是等价的:
if (10 == $x) { echo 'Yes'; } else { echo 'No'; }
正如你所见的那样,这种三元操作符异常简介——而且,合理的利用它可以是代码更容易阅读。那么你可以想象得到,没什么比这个更加简练了:可是过渡的使用会让代码难以理解并且影响运行效率,特别是采用连续嵌套的条件控制。
if-then-else的语法结构如果去连续判断一个值的不同情况将会变得复杂。想象这个有时会看到的这类连续的if-then-else写法:
$a = 0; if ($a) { // 条件为假 } elseif ($a == 0) { // 条件为真 } else { // 以上条件都不满足时就会执行这里的代码 }
这样的代码伴随着一堆问题,首先,庞大的代码量难于理解与维护。其次,$a中的值必须一次一次的去验证条件——不过在本例中并不算太大的问题,如果需要判断的是一个复杂的表达式,问题就大了。为了缓解这些问题,PHP推荐使用switch结构:
$a = 0; switch ($a) { // 本例运行的前提是$a是一个表达式 case true: // 与true比较 // 判断为假 break; case 0: // 与0比较 // 判断为真 break; default: // 只有当以上条件都为false时才执行 break; }
使用switch来判断一个表达式(本例中是$a),将其与逐个case值进行比较;如果表达式与case值比配则执行对应的语句直到遇到break就会跳出这个结构。需要提醒的是别忘记在case对应的语句末尾加上break——否则解释器会继续往下判断其他的case值。最后如果没有case值与其匹配,则解释器会运行default里的语句。
Siemen注:原文翻译叫做迭代结构,通俗起见就叫做循环控制。
循环控制提供了多次执行一段代码的能力。PHP提供了四种控制结构,通常其中两种是一门语言必须具备的。
最简单的循环结构是while()和do…while()循环;循环开始后会不计次数的执行其中的代码,直到给出的表达式为假时才会终止:
// Siemen注:这里的PHP_EOL是End of Line的缩写,预设常量,在UNIX系列的系统中为/n,WINDOWS系列的系统中为/r/n $i = 0; while ($i < 10) { echo $i . PHP_EOL; } $i = 0; do { echo $i . PHP_EOL; $i++; } while ($i < 10);
如你所见,这两段循环非常类似;唯一的区别在于判断条件的位置。在while()循环中,条件判断会在每次循环开始的时候执行——也就是说如果条件判断为假,那么循环中的语句将不会被执行。而在do…while()循环中,条件判断放在了循环末尾——意思就是就算条件判断为假,至少代码也执行了一次。
那么for和foreach结构是高级的循环机制,提供比while()更多的控制力,并且更容易代码理解:
for ($i = 0; $i < 10; $i++) { echo $i . PHP_EOL; }
与你看见的一样,for循环声明中有三个部分,每个部分之间使用分号间隔。第一部分包含了一条只在循环开始之前执行一次的指令(或者一系列多条指令,用逗号分隔)。第二部分包含了一个每次循环都会检查是否为真的条件,第三部分会在每次循环结束执行。因此下面这种写法也是等价的:
$i = 0; while ($i < 10) { echo $i . PHP_EOL; $i++; }
作者提示:以上出现的PHP_EOL是预设常量,相当于当前系统的“end of line”。
与for类似的foreach结构,是针对一个数组才操作的,这部分会在数组章节中详细介绍。
对于break这个关键字,我们在之前介绍swich的小节中已经遇到过了,这个关键字也可以被用来终端一个循环;将其嵌入循环中可以强制中断循环继续程序运行:
$i = 0; while (true) { if ($i = 10) { break; } echo $i . PHP_EOL; $i++ } for ($i =0; $i < 10; $i++) { for ($j = 0; $j < 3; $j++) { if (($j + $i) % 5 == 0) { break 2; // 退出里面的这个for循环,继续执行外面的这个for循环 } } }
作者提示:记住如果break后面不带参数的话记得加上分号。如果你没有这么做的话,如果这个break后面出现了表达式返回了一个整数,就有可能发生随机的程序中断——引起此种错误是很难排查的。
幸好有比break更好用的方法,当只是想要跳过当前循环的执行而继续下一轮循环。你可以利用continue语句来帮完成——用起来就像break,你也可以在后面跟随一个整数来说明你要跳过的循环属于哪一层。下面例子中将只输出0到3与5到9的数字:
for ($i = 0; $i < 10; $i++) { if ($i > 3 && $i < 6) { continue; } echo $i . PHP_EOL; }
修正:
2010年04月06日 —— Siemen
1. 所有代码部分使用csdn代码重新插入