php基础汇总
1 PHP 基础核心知识
1.1 PHP 语法与基础机制
1.1.1 PHP 的执行机制与基本语法
PHP(Hypertext Preprocessor)是一种广泛使用的开源通用脚本语言,特别适合于 Web 开发。它的核心特性在于服务器端执行:PHP 代码在服务器上运行,将处理后的纯 HTML 结果发送回客户端浏览器。这意味着用户无法在浏览器中查看到 PHP 的源代码。
PHP 脚本可以无缝嵌入到 HTML 文档的任何位置。标准的 PHP 脚本必须包裹在特定的标签中:
- 起始标签:
<?php - 结束标签:
?>
文件规范:PHP 文件的默认文件扩展名是 .php。一个合法的 PHP 文件通常混合包含了 HTML 标签、CSS、JavaScript 以及 PHP 脚本代码。
指令分隔:在 PHP 中,每一个指令代码行都必须以分号(;)作为结束符。分号是 PHP 引擎区分不同指令集的唯一标准,遗漏分号是初学者最常犯的语法错误。
1.1.2 基础输出指令
通过 PHP 向浏览器输出文本或变量,最基础且最常用的指令有两种:echo 和 print。
echo:可以输出一个或多个字符串,速度略快,没有返回值。print:只允许输出一个字符串,返回值总为 1。
1 | <?php |
1.1.3 PHP 中的注释规范
注释是代码中不可执行的部分,主要用于解释代码逻辑、标记作者信息或临时禁用某段代码。良好的注释习惯是优秀程序员的标志。
1 | <?php |
1.2 PHP 变量与作用域
1.2.1 变量的本质与命名规则
变量是用于存储信息的内存“容器”。与代数中的变量(如 $x=5, y=6, z=x+y$)类似,PHP 变量用于保存数据和表达式的结果。
严格的命名规则:
- 标识符前缀:所有变量必须以美元符号
$开始,紧跟变量名称。 - 首字符限制:变量名必须以英文字母或者下划线(
_)字符开始,绝对不能以数字开头。 - 字符集限制:变量名只能包含字母、数字以及下划线(即
A-z、0-9和_)。 - 禁止空格:变量名内部不能包含任何空格。如果需要包含多个单词,建议使用下划线命名法(
$my_car)或驼峰命名法($myCar)。 - 大小写敏感:PHP 的变量名是严格区分大小写的(
$age、$Age和$AGE是三个完全不同的变量)。注:PHP 的内置函数、类名等则不区分大小写。
1.2.2 弱类型语言的自动推导
PHP 是一门弱类型(动态类型)语言。这意味着你不需要在声明变量时指明其数据类型。变量在第一次被赋值时自动创建,并且 PHP 引擎会根据所赋的值自动推导出正确的数据类型。
1 | <?php |
1.2.3 变量作用域深度解析
作用域决定了变量在脚本中可被访问的可见范围。PHP 拥有四种主要的变量作用域:
1.2.3.1 局部作用域与全局作用域
全局变量:在所有函数外部定义的变量,拥有全局作用域。但在 PHP 中,函数内部无法直接访问外部的全局变量。
局部变量:在函数内部声明的变量,仅能在该函数内部访问。不同函数可以使用同名的局部变量而互不干扰。
如果必须在函数内部修改或读取全局变量,有两种方法:使用 global 关键字,或使用超级全局数组 $GLOBALS。
1 | <?php |
1.2.3.2 静态作用域
默认情况下,当函数执行完毕后,其内部的所有局部变量都会被销毁以释放内存。但有时我们需要保留某个局部变量的值供下一次函数调用时使用,这就需要用到 static 关键字。
1 | <?php |
1.2.3.3 参数作用域
参数是通过调用代码将值传递给函数的局部变量。它们在函数的参数列表中声明,其作用域等同于该函数的局部变量。
1 | <?php |
1.3 PHP 核心数据类型
PHP 支持 8 种原始数据类型,分为标量类型、复合类型和特殊类型。
1.3.1 标量数据类型
- String(字符串):一串字符序列。可以使用单引号或双引号。双引号会解析内部的变量,而单引号不会。
- Integer(整型):没有小数部分的数字。至少包含一个数字,不能包含逗号或空格。支持十进制、十六进制(
0x前缀)和八进制(0前缀)。 - Float(浮点型):带小数部分的数字,或指数形式。
- Boolean(布尔型):逻辑上的真(
TRUE)或假(FALSE),常用于条件控制。
1 | <?php |
1.3.2 复合数据类型
- Array(数组):在一个变量中存储多个独立的值。
- Object(对象):面向对象编程的核心。包含属性(变量)和方法(函数)的数据结构。必须首先使用
class关键字声明类,然后使用new实例化。
1 | <?php |
1.3.3 特殊数据类型
- NULL(空值):表示一个变量没有值。主要用于清空变量、区分变量是否被初始化。
- Resource(资源):保存了到外部资源的一个引用,比如数据库连接(MySQL link)、打开的文件句柄、图形画布区域等。
1 | <?php |
1.3.4 PHP 类型比较的陷阱 (松散与严格)
PHP 的弱类型特性导致了比较时的复杂性:
- 松散比较 (
==):只比较值。如果类型不同,PHP 会尝试进行类型转换后再比较。 - 严格比较 (
===):不仅比较值,还比较数据类型。推荐在生产环境中使用严格比较以避免隐式转换带来的 Bug。
1 | <?php |
1.4 PHP 数组操作全解析
数组是 PHP 中最强大的数据结构之一,它允许你在单个变量中存储、管理和操作大量数据。
1.4.1 数组的三种形态
- 数值数组(索引数组):带有数字 ID 键的数组。键名默认从 0 开始自动分配,也可手动干预。
- 关联数组(字典):带有指定字符串键的数组,每一个键映射一个具体的值。
- 多维数组:数组内部的元素也是数组,用于表示复杂的矩阵或层级数据。
1 | <?php |
1.4.2 数组排序机制
PHP 提供了针对不同需求的丰富排序函数:
- 数值数组排序:
sort()(升序),rsort()(降序)。 - 关联数组按“值”排序:
asort()(保持索引关系的升序),arsort()(降序)。 - 关联数组按“键”排序:
ksort()(按键名升序),krsort()(按键名降序)。
1 | <?php |
1.4.3 核心 PHP Array 函数速查手册
这是日常开发中最常使用的内置数组处理函数:
| 函数名 | 深度描述与用途 |
|---|---|
array() |
初始化并创建一个新的数组结构。 |
array_column() |
从多维数组中提取出一列所有的值,常用于处理数据库查询返回的二维数组集。 |
array_combine() |
传入两个数组,一个作为键名(Keys),一个作为键值(Values),合并为一个全新的关联数组。 |
array_count_values() |
频率分析神器:统计数组中每一个值出现的总次数,返回以值为键、次数为值的数组。 |
array_diff() |
计算并返回第一个数组与其它数组的差集(找不同,仅比较键值)。 |
array_filter() |
传入一个回调函数,对数组中的每个元素进行逻辑判断过滤,保留返回 TRUE 的元素。 |
array_flip() |
键值对调:将数组中的键名变成键值,原来的键值变成键名。 |
array_intersect() |
计算并返回多个数组的交集(找相同点,仅比较键值)。 |
array_key_exists() |
安全检查:判断指定的键名是否存在于给定的数组中,返回布尔值。 |
array_keys() |
剥离所有的键值,仅返回一个包含原数组所有键名的新数值数组。 |
array_map() |
将用户自定义的回调函数应用到给定数组的每一个值上,返回处理后的新数组(类似数据清洗)。 |
array_merge() |
将一个或多个数组的单元合并起来,一个数组中的值附加在前一个数组的后面。 |
array_pop() |
数据结构中的“出栈”操作:弹出并返回数组的最后一个元素,数组长度减一。 |
array_push() |
数据结构中的“入栈”操作:向数组的末尾压入一个或多个元素。 |
array_shift() |
数据结构中的“出队”操作:移出并返回数组的第一个元素。 |
array_unshift() |
向数组的最开头插入一个或多个元素。 |
array_sum() |
计算数组中所有数值元素的总和。 |
array_unique() |
数据去重:移除数组中所有重复的值,仅保留第一个出现的条目。 |
count() |
获取数组内部元素的总个数(等同于 sizeof())。 |
in_array() |
搜索指定的值是否存在于数组中,常用于白名单校验。 |
1.5 常量与魔术常量
1.5.1 PHP 常量的定义与特性
常量是指一旦在脚本中定义后,其值绝对不能被改变或重新定义的标识符。
- 全局有效:常量不受变量作用域的限制,定义后可以在脚本的任何地方(包括函数内部)直接使用,无需
global关键字。 - 没有
$符号:常量名在使用和定义时都不带美元符号。 - 命名规范:通常使用全大写字母加下划线命名(如
DB_PASSWORD)。
定义常量的两种方式:
define(name, value, case_insensitive)函数:运行时定义。PHP 8.0 开始废弃了大小写不敏感(第三个参数设为 true)的设定。const关键字:编译时定义,执行效率略高。PHP 7+ 开始支持使用const定义数组常量。
1 | <?php |
1.5.2 PHP 魔术常量 (Magic Constants)
PHP 提供了几个特殊的预定义常量,被称为“魔术常量”。它们之所以“魔术”,是因为它们的值会随着代码位置的改变而动态变化。它们在日志记录、框架路由和调试时不可或缺。
| 魔术常量 | 动态返回值描述 |
|---|---|
__LINE__ |
返回该常量在当前文件中所处的绝对行号(常用于错误日志追踪)。 |
__FILE__ |
返回当前执行脚本的完整物理路径和文件名(如 C:\xampp\htdocs\index.php)。 |
__DIR__ |
返回当前文件所在的目录路径(等同于 dirname(__FILE__),常用于包含相对路径的文件)。 |
__FUNCTION__ |
返回当前正在执行的函数的名称。 |
__CLASS__ |
返回当前被定义的类的名称(包含命名空间)。 |
__TRAIT__ |
返回当前正在使用的 Trait 代码复用块的名字。 |
__METHOD__ |
返回当前正在调用的类方法名(格式为 ClassName::MethodName)。 |
__NAMESPACE__ |
返回当前代码所处的命名空间名称。 |
1 | <?php |
1.6 字符串变量与函数速查
字符串操作是 Web 后端开发中最频繁的动作。PHP 提供了强大的原生的字符串拼接与解析能力。
1.6.1 字符串基本操作与并置
在 PHP 中,只有一个专用的字符串运算符:并置运算符 (.),它用于将两个或多个字符串拼接在一起。
除了拼接,获取长度和查找位置是两大基础需求:
strlen():获取字符串的字节长度。strpos():在母字符串中检索子串首次出现的位置(索引从 0 开始。如果未找到则返回 FALSE)。
1 | <?php |
1.6.2 复杂多行字符串声明 (Heredoc 语法)
除了单引号和双引号,PHP 还提供了一种专门用于定义大段多行文本(尤其是包含 HTML 结构时)的利器:Heredoc (EOF) 语法。
使用 <<< 加上一个标识符(通常习惯用 EOF、EOD 或 HTML)来标记字符串的开始。
Heredoc 的五大核心铁律:
- 开始标记:
<<<EOF后面不能有任何字符(包括空格)。 - 变量解析:位于开始和结束标记之间的 PHP 变量会被正常解析(就像双引号一样),而且不需要使用
.来拼接,直接写在文本里即可。但函数不能直接在里面解析。 - 无需转义:在内容中直接嵌套单引号或双引号时,不需要加反斜杠转义,非常适合写大段的 HTML。
- 结束标记极其严格:结束标记
EOF;必须顶头独立占一行!它的前面不能有缩进、不能有空格,后面除了分号外也不能有任何字符。 - 标识符一致:开始的标识符和结束的标识符必须完全一致。
代码示例:
1 | <?php |
1.6.3 核心 PHP String 函数全景手册
PHP 核心自带了海量的字符串处理函数,以下是必须掌握的完整列表清单:
| 函数名称 | 核心业务用途描述 |
|---|---|
addslashes() |
防注入基础:在预定义的特殊字符(单引号、双引号、反斜杠、NULL)前面添加反斜杠进行转义。 |
stripslashes() |
数据还原:删除由 addslashes() 函数添加的反斜杠。 |
explode() |
字符串切片:根据指定的分隔符,把一个长字符串打散成一个数组。 |
implode() |
(等同于 join())把数组的所有元素按照指定的连接符拼装成一个单一长字符串。 |
htmlspecialchars() |
XSS防御核心:把预定义的字符(如 < 和 >)转换为 HTML 实体,防止浏览器将其解析为执行代码。 |
html_entity_decode() |
将 HTML 实体重新反转码回普通字符。 |
md5() |
哈希加密:计算字符串的 32 位 MD5 散列值(通常用于密码存储或文件校验)。 |
sha1() |
计算字符串的 SHA-1 散列值(比 MD5 更安全一点的算法)。 |
nl2br() |
格式化文本:自动在字符串中所有的换行符(\n)之前插入 HTML 的 <br> 换行标签。 |
str_replace() |
全局替换:在原字符串中查找所有指定的值,并替换为新的值(大小写敏感)。 |
str_ireplace() |
全局替换(大小写不敏感版本)。 |
strcmp() |
安全比较:对比两个字符串是否完全一致(返回 0 表示相等)。大小写敏感。 |
strcasecmp() |
安全比较:对比两个字符串。大小写不敏感。 |
strip_tags() |
净化文本:剥去字符串中包含的所有 HTML 和 PHP 标签,只保留纯文本。 |
strlen() |
返回字符串的字节数长度。(注意:处理中文字符应使用扩展函数 mb_strlen())。 |
strpos() |
查找字符串在另一字符串中第一次出现的位置(从左向右)。 |
strrpos() |
查找字符串在另一字符串中最后一次出现的位置(从右向左)。 |
strtolower() |
格式化:把字符串中的所有英文字符转换为纯小写。 |
strtoupper() |
格式化:把字符串中的所有英文字符转换为纯大写。 |
substr() |
截取字符串:根据指定的起始位置和长度,返回字符串的一部分片段。处理中文用 mb_substr()。 |
trim() |
清理数据:移除字符串左右两侧的空白字符(包括空格、制表符、换行符等)。 |
ltrim() / rtrim() |
仅移除左侧(ltrim)或右侧(rtrim)的空白字符。 |
1.7 PHP 超级全局变量 (Superglobals)
超级全局变量是在 PHP 4.1.0 之后引入的核心概念。它们是预定义的内部数组,在一个脚本的全部作用域中都可用,无需跨越函数边界声明 global。
1.7.1 $GLOBALS
一个包含了当前执行脚本中全部全局变量的关联数组。数组的键(Key)就是全局变量的名称。你可以在函数的任何角落随时存取。
1.7.2 $_SERVER (服务器环境变量表)
$_SERVER 是一个由 Web 服务器(如 Nginx, Apache)在每次请求时创建和填充的数组。它包含了大量的头信息、执行路径、以及客户端请求详情。这是开发后端路由和安全过滤的基石。
最核心的 $_SERVER 参数大全:
| 键名 (Key) | 详细数据描述与应用场景 |
|---|---|
$_SERVER['PHP_SELF'] |
当前正在执行的脚本相对于网站根目录的文件名。常用于表单自提交的 action 路径。 |
$_SERVER['SERVER_ADDR'] |
运行当前 PHP 脚本的后端服务器的真实物理 IP 地址。 |
$_SERVER['SERVER_NAME'] |
服务器的主机名或虚拟主机配置名称(如 www.example.com)。 |
$_SERVER['REQUEST_METHOD'] |
客户端访问该页面所使用的 HTTP 动词,如 GET, POST, PUT, DELETE 等。 |
$_SERVER['REQUEST_TIME'] |
该 HTTP 请求开始发起时的 Unix 绝对时间戳。 |
$_SERVER['QUERY_STRING'] |
URL 中问号 ? 后面的所有查询字符串内容(如 id=5&type=admin)。 |
$_SERVER['HTTP_USER_AGENT'] |
客户端浏览器的 User-Agent 字符串。常用于判断设备类型(手机/PC)或拦截爬虫。 |
$_SERVER['HTTP_REFERER'] |
引导用户跳转到当前页面的前一个网页的 URL(注意:此值由客户端浏览器发送,容易被伪造,不可用于严格的安全校验)。 |
$_SERVER['REMOTE_ADDR'] |
发起请求的客户端(用户)的真实 IP 地址。 |
$_SERVER['SCRIPT_FILENAME'] |
当前执行脚本在服务器硬盘上的绝对物理路径(如 /var/www/html/index.php)。 |
1.7.3 $_REQUEST, $_POST, $_GET 表单数据接收
$_GET:接收通过 URL 地址栏传递的参数(HTTP GET 方法)。数据暴露在明文中,有长度限制,适合用于搜索查询或分页参数。$_POST:接收通过 HTTP POST 方法在请求体中传递的数据。数据对终端用户不可见,无体积限制,绝对用于密码、大文本等敏感或大规模数据的传输。$_REQUEST:一个综合性的数组,默认包含了$_GET、$_POST和$_COOKIE的所有数据。虽然方便,但在追求安全的现代框架中不推荐使用,应当明确区分请求来源。
1 | <html> |
1.8 函数定义与变量函数
1.8.1 函数的基础架构
函数是可重用代码块的封装。
- 使用
function关键字定义。 - 可以通过参数列表(括号内的变量)接收外部传入的数据。
- 可以通过
return语句将内部计算的结果返回给调用方。
1 | <?php |
1.8.2 变量函数 (可变函数)
PHP 拥有一个非常灵活的特性:如果一个变量名后面紧跟了一对圆括号 (),PHP 引擎将会在内部寻找与该变量的值同名的函数,并尝试执行它。这在实现回调机制、路由分发或工厂模式时极为强大。
1 | <?php |
1.9 内置函数
内置函数是 PHP 核心(或通过扩展模块)预先定义好的、在运行时被调用的代码封装。与语言结构在底层编译阶段被解析不同,内置函数遵循严格的面向过程的函数调用规范。
1.9.1.1 内置函数的核心特性(与语言结构对比)
必须严格使用括号
(): 这是内置函数最致命的语法限制。无论该函数是否需要接收参数,调用时都必须带上括号。例如phpinfo();是合法的,但写成phpinfo;会导致语法错误。_(这也是为什么在 CTF 中一旦过滤了左括号(,所有内置函数集体失效的原因)_。支持“变量函数”动态调用: 这是内置函数极其强大(也极其危险)的特性。你可以将函数名赋值给一个变量,然后通过该变量来动态调用函数。例如:
PHP
1
2$func = 'system';
$func('whoami'); // 等同于执行 system('whoami');_(注:这种特性常被用于编写高度隐蔽的一句话木马,或者在 WAF 绕过中进行函数名的字符串拼接。)_
具有标准返回值: 绝大多数内置函数执行完毕后都会返回一个结果(布尔值、字符串、数组或资源等),因此它们的执行结果可以直接赋值给其他变量。例如
$len = strlen("hello");。不区分大小写: 虽然不推荐,但 PHP 的内置函数名(包括自定义函数名)是不区分大小写的,
System('ls')和system('ls')效果相同。
1.9.1.2 常见的核心内置函数分类(按安全审计敏感度划分)
在代码审计和 CTF 实战中,我们通常会高度关注以下几类内置函数:
- 系统命令执行类(极度危险):
system()/passthru()(执行外部程序并显示输出)exec()/shell_exec()(执行外部程序,通常需要 return 或 echo 输出)
- 文件读取与高亮类:
file_get_contents()(将整个文件读入一个字符串,支持伪协议)highlight_file()/show_source()(语法高亮一个文件,常用于读取 flag 源码)readfile()(输出一个文件)
- 代码执行与处理类:
preg_replace()(在 PHP 5.5 以下版本中,如果使用/e修饰符,会导致代码执行)assert()(在 PHP 7 之前,如果参数是字符串,会被当做 PHP 代码执行)call_user_func()/call_user_func_array()(用于回调函数,是利用变量函数的进阶手段)
- 变量与信息查看类:
phpinfo()(输出当前 PHP 环境的超详细信息,常作为测试执行漏洞的探针)var_dump()/print_r()(注意:print是语言结构,但print_r是正儿八经的内置函数)
在漏洞挖掘中,内置函数的**“变量函数动态调用”机制是攻击者的最爱,例如利用 $_GET['a']($_GET['b']) 配合 ?a=system&b=ls 即可轻松 RCE。 然而,防守方一旦在正则表达式中加入针对括号 () 或者关键字(如 system, exec)的过滤,攻击者就不得不放弃内置函数,转而去寻找“语言结构”来作为替代方案。
1.10 语言结构
不同于内置函数,语言结构是 PHP 语法引擎(Zend Engine)本身的一部分,它们在词法分析和编译阶段就被直接解析,而不是像普通函数那样在运行时被调用。
1.10.1.1 与内置函数的核心区别
- 不需要括号: 这是最显著的特征。语言结构可以直接跟参数,例如
echo "hello";或include "flag.php";。而函数即使没有参数也必须带括号,如phpinfo();。 - 允许无空格解析: 当语言结构后面紧跟的是变量(以 符号天然区分边界,因此不需要空格。例如
include$a;是合法的,但system$a;会报语法错误(Parse error)。 - 不支持变量函数调用: 你不能用变量来动态调用语言结构。例如
$func = 'echo'; $func('test');会报错,但如果$func = 'system';就可以正常执行。 - 行为不受限于函数规则: 有些语言结构没有返回值(如
echo),不能像函数那样赋值给变量(如$a = echo "1";是错误的)。
1.10.1.2 常见的 PHP 语言结构汇总
在日常开发和代码审计中,最常遇到的语言结构可分为以下几类:
- 输出/中断类:
echo/print(输出内容)die/exit(输出内容并终止脚本运行)
- 文件包含类(重要):
include/include_oncerequire/require_once
- 变量处理类:
isset(检测变量是否已声明且不为 null)empty(检查变量是否为空)unset(释放给定的变量)
- 代码执行类:
eval(注意: 这是一个极其特殊的语言结构,它虽然属于语言结构,但在 PHP 语法规定中必须使用括号,即eval(...))。
1.11 全面解析 PHP 运算符
运算符是指令引擎如何处理数据变量的符号集。
1.11.1 算术与赋值运算符
算术:加
+、减-、乘*、除/、模(求余)%、按位取反~。(PHP 7+ 新增整除函数
intdiv(10, 3)返回 3)赋值:基本赋值
=,它会将右侧的值载入左侧变量。结合算术可形成复合赋值:+=,-=,*=,/=,%=,.=(字符串追加赋值)。
1.11.2 递增/递减运算符的执行顺序差异
非常容易出错的考点:放在前面和放在后面的区别。
- 预递增
++$x:先将变量加 1,然后再将增加后的值用于当前表达式。 - 后递增
$x++:先将变量的当前值用于表达式计算,然后再给自身加 1。
1 | <?php |
1.11.3 逻辑运算符优先级陷阱
and/&&:逻辑与(两者皆为真才为真)。or/||:逻辑或(任一为真即为真)。xor:异或(有且仅有一个为真时返回真,都为真或都为假则返回假)。!:逻辑非(取反)。
优先级考点: && 和 || 的优先级高于赋值运算符 =,而英文单词格式的 and 和 or 优先级低于赋值运算符。
1 | <?php |
1.11.4 高级比较符:三元、NULL合并与太空船
现代 PHP 提供了极其优雅的单行条件判断符号:
- 传统三元运算符 (
?:):条件 ? 真值 : 假值。如果条件成立返回第一项,否则第二项。自 PHP 5.3 起可简写为条件 ?: 假值(如果条件本身有值就返回条件自身)。 - NULL 合并运算符 (
??, PHP 7+):用于替代isset()判断。如果变量存在且不为 NULL,就返回它本身,否则返回右侧给定的默认值。 - 组合比较符/太空船操作符 (
<=>, PHP 7+):实现全方位比对。- 左边 > 右边,返回
1 - 左右相等,返回
0 - 左边 < 右边,返回
-1
- 左边 > 右边,返回
1 | <?php |
1.12 逻辑控制流与循环结构
逻辑语句指导了代码的执行路径。
1.12.1 条件控制分支 (If / Switch)
if...else:用于处理连续的范围判断或复杂的复合逻辑。switch...case:专门处理针对同一个变量匹配多个离散固定的“值”的情况。switch性能更优且结构清晰。千万别忘记写break;,否则代码会发生“贯穿(fall-through)”,错误地执行下一个 case 的代码。
1 | <?php |
1.12.2 循环的艺术 (While / For / Foreach)
使你的服务器能够在一瞬间处理成千上万条记录的利器:循环。
while循环:先判断条件。只有当给定条件为 TRUE 时才进入循环体执行。适合不知道具体迭代次数,只依赖某个阈值的场景。do...while循环:先执行,后判断。特点是至少会强制执行一次循环体内的代码,然后才开始检查条件。for循环:用于预先明确知道需要执行多少次的场景。它的结构(初始值设置;条件判断界限;计数器增量)被整齐地排列在代码行头部,一目了然。foreach循环:专为遍历数组和对象属性而生。无需手动设置计数器或判断边界,引擎会自动剥离出数组当前的“键(Key)”和“值(Value)”,并在内部移动指针,直到遍历完所有元素。
1 | <?php |

