PHP 流程控制
PHP 脚本是由各种各样的语句组成的,这些语句告诉计算机如何执行任务。通过学习这些语句,我们就可以编写出各种各样的 PHP 程序。
if 语句
if 结构让程序能够根据不同的输入或状态做出不同的反应,从而实现复杂的逻辑控制。if 结构就像是一个“如果……那么……”的判断,它告诉计算机:如果某个条件成立,就执行特定的代码;如果不成立,就执行其他的代码或者什么都不做。
示例,如果 $a
大于 $b
,则以下例子将显示 a is bigger than b:
<?php
if ($a > $b)
echo "a is bigger than b";
?>
如果语句块只有一条语句,可以省略花括号。但是为了代码的可读性和避免错误,建议始终使用花括号。
else
当 if
语句中的条件不满足时,else
语句块中的代码就会被执行。这就像是在做选择题时,如果选A不对,那么就选B。
示例:
<?php
if ($a > $b) {
echo "a is bigger than b";
} else {
echo "a is NOT bigger than b";
}
?>
elseif/else if
elseif
语句在 if
语句的基础上提供了更多的条件判断分支。它允许你在多个条件中进行选择,一旦某个 elseif
的条件满足,就会执行其对应的代码块,而不再继续判断后续的条件。
示例:
<?php
if (条件1) {
// 条件1为真时执行的代码
} elseif (条件2) {
// 条件2为真时执行的代码
} elseif (条件3) {
// 条件3为真时执行的代码
} else {
// 所有条件都不满足时执行的代码
}
?>
elseif 和 else if 的区别
elseif
是一个关键字,而 else if
是两个关键字。在 PHP 中,elseif
和 else if
都可以正常使用,但 elseif
更常用。两者功能是完全一样的。
流程控制的替代语法
PHP 提供的替代语法,将传统的 {}
花括号替换为 :
冒号和相应的结束标志,如 endif
、endwhile
等,这种语法风格在某些场景下具有以下优势:
- 可读性增强: 对于嵌套较深的控制结构,替代语法能更清晰地表示出代码块的开始和结束,减少了视觉上的干扰。
- 与其他模板引擎的兼容性: 这种语法风格与一些模板引擎(如 Smarty)的语法相似,方便在 PHP 和模板引擎之间切换。
示例:
<?php
// if...else 语句
if ($age >= 18):
echo "You are an adult.";
elseif ($age >= 13):
echo "You are a teenager.";
else:
echo "You are a child.";
endif;
// while 循环
$i = 0;
while ($i < 5):
echo $i;
$i++;
endwhile;
// for 循环
for ($i = 0; $i < 10; $i++):
echo $i . " ";
endfor;
// foreach 循环
$colors = array("red", "green", "blue");
foreach ($colors as $value):
echo "$value <br>";
endforeach;
?>
注:在同一个控制块内,不能同时使用传统语法和替代语法。
while
while
循环允许你重复执行一段代码,直到指定的条件不再满足。换句话说,只要 while 后面的条件表达式为真(true),循环就会一直进行。
示例:
<?php
$i = 1;
while ($i <= 5) {
echo "数字是: $i <br>";
$i++;
}
?>
do-while
do-while 循环 与 while 循环 的核心区别就在于 条件判断的时机 不同。
- while 循环: 先判断条件,如果条件为真,则执行循环体;如果条件为假,则直接跳过循环体。
- do-while 循环: 先执行循环体,然后再判断条件。也就是说,do-while 循环至少会执行一次。
示例:
<?php
do {
if ($i < 5) {
echo "i is not big enough";
break;
}
$i *= $factor;
if ($i < $minimum_limit) {
break;
}
echo "i is ok";
/* process i */
} while(0);
?>
选择 while 循环还是 do-while 循环?如果循环体至少需要执行一次,那么 do-while 循环更合适;如果需要在循环开始前判断条件,那么 while 循环更合适。
for
for
循环 更适合用于次数确定的循环,而 while 循环 更适合用于条件满足时执行的循环。语法:
for (初始化; 条件; 增量) {
// 要重复执行的代码
}
初始化: 在循环开始前执行一次,通常用于初始化循环变量。
条件: 在每次循环开始前进行判断,如果为真,则执行循环体;否则退出循环。
增量: 在每次循环结束后执行,通常用于更新循环变量。
foreach
foreach
循环是 PHP 中专门用于遍历数组和对象的循环结构(只能用于数组和对象,不能用于其他数据类型
)。它提供了一种非常简洁的方式来访问数组中的每个元素或对象的每个属性。
foreach 语法的两种形式:
1、foreach (iterable_expression as $value) statement
示例:
<?php
$colors = array("red", "green", "blue");
foreach ($colors as $color) {
echo $color . "<br>";
}
?>
这段代码会依次输出:
<code>red
green
blue
2、foreach (iterable_expression as $key => $value) statement
示例:
<?php
$ages = array("Peter"=>35, "Ben"=>37, "Joe"=>43);
foreach($ages as $x => $x_value) {
echo "Key=" . $x . ", Value=" . $x_value;
}
?>
这段代码会输出:
<code>Key=Peter, Value=35
Key=Ben, Value=37
Key=Joe, Value=43
foreach 不会修改内部指针
foreach 是一种特殊的循环结构,它在内部维护了一个独立的指针,用于遍历数组或对象。当使用 foreach 时,PHP 会自动创建一个内部指针,指向数组或对象的第一个元素。每次循环,这个指针都会自动向后移动一位。因此,foreach 不会影响其他函数对数组内部指针的操作。
在处理数组和对象时,foreach 是首选的循环方式。
break
break
语句主要用于在循环或 switch
语句中提前终止循环。它相当于给循环下达了一个“停止”命令,一旦遇到 break
,程序就会跳出当前的循环结构,继续执行后面的代码。
示例:
<?php
for ($i = 0; $i < 10; $i++) {
if ($i == 5) {
break;
}
echo $i . " ";
}
?>
这段代码会输出 0 1 2 3 4,当 $i 等于 5 时,break 语句就会执行,直接跳出循环,后面的数字就不会再输出了。
break 可以带一个数字参数,指定跳出几层循环(默认是 1)。break 只能用在循环或 swi
tch
结构中,不能用在 if 语句中。
continue
continue
语句与 break
语句一样,都是用来控制循环的流程的,但是它们的作用略有不同。当程序执行到 continue
语句时,会立即跳过本次循环的剩余部分,直接进入下一次循环的判断。虽然跳过了本次循环,但整个循环并没有终止,程序会继续执行后续的循环。
示例:
<?php
for ($i = 0; $i < 10; $i++) {
if ($i % 2 == 0) {
continue; // 跳过偶数
}
echo $i . " ";
}
?>
这段代码会输出:
<code>1 3 5 7 9
switch
switch
语句 可以看作是一种特殊的 if else if else 结构,专门用来处理多个等值判断的场景。switch 语句只能判断一个表达式是否等于一系列常量值
,而 if else 可以进行更复杂的条件判断,比如大于、小于、不等于等。
语法:
switch (表达式) {
case 值1:
// 代码块1
break;
case 值2:
// 代码块2
break;
// ...
default:
// 默认代码块
}
需注意的地方
- case 的值必须是常量或表达式:不能使用变量。
- break 是可选的:如果没有 break,程序会继续执行下一个 case 的代码块,直到遇到 break 或 switch 语句结束。
- default 是可选的:如果没有匹配的 case,并且没有 default,则什么也不做。
示例:
<?php
$fruit = "apple";
switch ($fruit) {
case "apple":
echo "苹果";
break;
case "banana":
echo "香蕉";
break;
case "orange":
echo "橙子";
break;
default:
echo "未知水果";
}
?>
以上代码会输出:
<code>苹果
switch 语句与 if else 的区别
- switch 语句 更适合用于多个等值比较,而 if else 语句更适合用于多个条件的组合判断。
- switch 语句 的效率通常比多个 if else 语句更高,尤其是当比较的值比较多时。
match
match
表达式是一种在 PHP 8.0 中引入的新的控制流结构,它提供了一种更简洁、更安全的方式来进行条件判断和分支执行。
语法:
match (表达式) {
值1 => 表达式1,
值2 => 表达式2,
...
default => 表达式,
};
工作原理:
- 计算表达式:首先计算
match
后面的表达式,得到一个值。 - 逐一比较:将计算得到的值与每个分支的
值
进行严格比较(===)。 - 匹配成功:一旦找到匹配的分支,就执行对应的
表达式
,并立即退出match
表达式。 - 没有匹配:如果没有找到匹配的分支,则执行
default
分支(如果存在)。
示例:
<?php
$color = 'red';
$result = match ($color) {
'red' => '苹果是红色的',
'green' => '草是绿色的',
'blue' => '天空是蓝色的',
default => '未知的颜色',
};
echo $result; // 输出:苹果是红色的
?>
match 表达式与 switch 语句的对比
特点 | switch 语句 | match 表达式 |
---|---|---|
比较方式 | 松散比较(==) | 严格比较(===) |
返回值 | 没有返回值,直接执行代码块 | 返回一个值 |
语法 | 更传统,case 语句 | 更现代,箭头函数语法 |
类型安全 | 类型不安全,可能导致隐式类型转换 | 类型安全,避免类型转换错误 |
在很多场景下,match 表达式都可以替代传统的 switch 语句,提高代码的可读性和可维护性。
declare
declare
结构在 PHP 中是一个比较特殊的语法,它用来设定一段代码的执行指令。你可以把它想象成给一段代码加上一个特殊的“标签”,告诉 PHP 解释器:这段代码应该如何执行。
语法:
declare (directive)
statement
directive: 指令,用来指定要设置的执行指令。目前 PHP 支持的指令有:
ticks
: 用于设置时钟周期,可以用来实现自定义的计时器。encoding
: 用于指定脚本的编码方式。strict_types
: 用于声明严格类型,要求函数参数和返回值的类型必须严格匹配。
statement: 要执行的代码块,就是受到 directive
指令影响的代码。
示例,指定脚本编码:
<?php
declare(encoding='UTF-8') {
// 所有字符都按照 UTF-8 编码处理
echo "你好,世界!";
}
?>
目前 PHP 支持的指令相对较少,但它们在某些特定的场景下非常有用。
return
return
语句在 PHP 中的主要作用是:
- 结束函数的执行: 一旦在函数内部遇到 return 语句,函数就会立即停止执行,不再执行后面的代码。
- 返回一个值: return 后面可以跟一个表达式,这个表达式的值就会作为函数的返回值,返回给调用者。
require 和 include
require
和 include
都用于在 PHP 脚本中引入其他文件的内容,但它们在处理文件引入失败时的行为上存在显著差异。
功能 | require | include |
---|---|---|
作用 | 引入文件 | 引入文件 |
错误处理 | 失败产生致命错误,脚本终止 | 失败产生警告,脚本继续 |
适用场景 | 核心文件,容错性低 | 非核心文件,容错性高 |
require_once 和 include_once
require_once
和 include_once
与 require
和 include
的主要区别在于它们能够 防止同一个文件被多次引入。一旦一个文件被 require_once
或 include_once
引入,PHP 会记录下这个文件,如果再次尝试引入相同的文件,就会被忽略。
如果一个文件中定义了函数、类或者变量,那么重复引入这个文件会导致这些定义被重复声明,从而引发错误。使用 require_once
或 include_once
可以有效避免这种情况。
goto
goto
语句是一个比较特殊的控制流语句,它允许你无条件地跳转到程序中的另一个指定位置。这个指定位置就像是一个“书签”,你可以在需要的时候直接跳到那里继续执行。语法:
goto 标签名;
// ...
标签名:
// 要跳转到的代码
标签名,是一个唯一的标识符,用冒号结尾,用来标记要跳转到的位置。goto 的跳转范围限制在同一个函数内,你不能跨函数使用 goto。goto 可以跳出循环或 switch 结构,但不能从外部跳入它们。