2025 PHP7/8 实战入门:15 天精通现代 Web 开发——第 5 课:数组与字符串处理
第 5 课:数组与字符串处理
一、学习目标
- 精通 PHP 数组的创建、遍历与常用操作
- 掌握 PHP7/8 数组新特性(常量数组、数组展开等)
- 熟练运用字符串函数与正则表达式处理文本
- 能够解决实际开发中的数组与字符串常见问题
二、核心知识点
(一)PHP 数组基础
数组的定义与分类
- 索引数组:以数字为键(默认从 0 开始),适合存储有序数据
- 关联数组:以字符串为键,适合存储键值对应的数据(如用户信息)
- PHP7 + 支持短数组语法(
[]
替代array()
,更简洁)
示例:
<?php // 1. 索引数组(两种写法等价) $fruits1 = array("苹果", "香蕉", "橙子"); $fruits2 = ["苹果", "香蕉", "橙子"]; // PHP7+推荐短语法// 2. 关联数组 $user = ["id" => 1,"name" => "张三","age" => 25,"email" => "zhangsan@example.com" ];// 3. 混合数组(不推荐,易混淆) $mixed = ["name" => "李四",0 => "学生","age" => 20 ]; ?>
数组元素的访问与修改
- 索引数组:通过数字键访问(如
$fruits[0]
) - 关联数组:通过字符串键访问(如
$user['name']
) - 新增元素:直接给不存在的键赋值(如
$fruits[3] = "葡萄"
) - 修改元素:给已存在的键重新赋值(如
$user['age'] = 26
)
示例:
<?php $user = ["id" => 1,"name" => "张三","age" => 25 ];// 访问元素 echo "姓名:{$user['name']}<br>"; // 输出:姓名:张三 echo "年龄:{$user['age']}<br>"; // 输出:年龄:25// 修改元素 $user['age'] = 26; echo "修改后年龄:{$user['age']}<br>"; // 输出:修改后年龄:26// 新增元素 $user['gender'] = "男"; print_r($user); // 输出:Array ( [id] => 1 [name] => 张三 [age] => 26 [gender] => 男 ) ?>
- 索引数组:通过数字键访问(如
数组的长度与判断
count($arr)
:返回数组元素个数(支持所有数组类型)empty($arr)
:判断数组是否为空(元素个数为 0 或数组未定义)isset($arr[$key])
:判断数组中指定键是否存在
示例:
<?php $empty_arr = []; $user = ["name" => "张三", "age" => 25];echo "user数组长度:" . count($user) . "<br>"; // 输出:2 echo "empty_arr是否为空:" . (empty($empty_arr) ? "是" : "否") . "<br>"; // 输出:是 echo "user中是否存在'email'键:" . (isset($user['email']) ? "是" : "否") . "<br>"; // 输出:否 ?>
(二)数组常用函数与新特性
数组遍历函数
foreach
:最常用,支持索引和关联数组(推荐)array_map
:对数组每个元素应用回调函数,返回新数组array_filter
:根据回调函数筛选数组元素,返回符合条件的新数组array_reduce
:将数组元素逐步缩减为单一值(如求和、拼接)
示例:
<?php $numbers = [1, 2, 3, 4, 5];// 1. array_map:将每个元素乘以2 $doubled = array_map(function(int $num): int {return $num * 2; }, $numbers); print_r($doubled); // 输出:Array ( [0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 10 )// 2. array_filter:筛选出偶数 $evens = array_filter($numbers, function(int $num): bool {return $num % 2 == 0; }); print_r($evens); // 输出:Array ( [1] => 2 [3] => 4 )// 3. array_reduce:计算数组总和 $total = array_reduce($numbers, function(int $carry, int $num): int {return $carry + $num; }, 0); // 0为初始值 echo "数组总和:{$total}<br>"; // 输出:15 ?>
PHP7 数组新特性
- 常量数组:
define()
支持定义数组(PHP7+),之前仅支持标量 - 数组展开:用
...
展开数组元素(PHP7.4+),简化数组合并
示例:
<?php // 1. 常量数组(PHP7+) define("FRUITS", ["苹果", "香蕉", "橙子"]); echo FRUITS[0]; // 输出:苹果// 2. 数组展开(PHP7.4+) $arr1 = [1, 2, 3]; $arr2 = [...$arr1, 4, 5]; // 展开$arr1,合并为新数组 print_r($arr2); // 输出:Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 )$user1 = ["name" => "张三", "age" => 25]; $user2 = [...$user1, "email" => "zhangsan@example.com"]; // 展开关联数组 print_r($user2); // 输出:Array ( [name] => 张三 [age] => 25 [email] => zhangsan@example.com ) ?>
- 常量数组:
PHP8 数组新特性
- 数组键名自动生成:数字键名自动递增(修复 PHP7 的不一致问题)
array_is_list()
:判断数组是否为 “列表”(键为连续数字,从 0 开始)
示例:
<?php // 1. 数组键名自动生成(PHP8) $arr = [10, 20, 30, "a" => 40, 50]; print_r($arr); // PHP8输出:Array ( [0] => 10 [1] => 20 [2] => 30 [a] => 40 [3] => 50 ) // PHP7输出:Array ( [0] => 10 [1] => 20 [2] => 30 [a] => 40 [4] => 50 )(键从4开始)// 2. array_is_list()(PHP8+) $list1 = [1, 2, 3]; $list2 = ["a" => 1, "b" => 2]; $list3 = [1, "a" => 2, 3];var_dump(array_is_list($list1)); // bool(true) var_dump(array_is_list($list2)); // bool(false) var_dump(array_is_list($list3)); // bool(false) ?>
多维数组处理
- 数组的元素可以是另一个数组(形成二维 / 三维数组)
- 常用于存储复杂数据(如用户列表、订单列表等)
示例:
<?php // 二维数组(用户列表) $users = [["id" => 1,"name" => "张三","age" => 25,"hobbies" => ["篮球", "游戏"]],["id" => 2,"name" => "李四","age" => 22,"hobbies" => ["读书", "旅行"]] ];// 遍历二维数组 foreach ($users as $user) {echo "姓名:{$user['name']},爱好:" . implode("、", $user['hobbies']) . "<br>"; } // 输出: // 姓名:张三,爱好:篮球、游戏 // 姓名:李四,爱好:读书、旅行// 用array_map处理二维数组(获取所有用户名) $names = array_map(function(array $user): string {return $user['name']; }, $users);print_r($names); // 输出:Array ( [0] => 张三 [1] => 李四 ) ?>
(三)字符串处理
字符串定义与转义
- 单引号:不解析变量和转义字符(除
\'
),性能更高 - 双引号:解析变量和转义字符(如
\n
换行、\t
制表符) - heredoc/nowdoc:适合大段文本(heredoc 解析变量,nowdoc 不解析)
示例:
<?php $name = "张三";// 1. 单引号(不解析变量) echo 'Hello, $name!<br>'; // 输出:Hello, $name!// 2. 双引号(解析变量) echo "Hello, $name!<br>"; // 输出:Hello, 张三! echo "换行符:\n制表符:\t测试<br>"; // 输出带格式的文本// 3. heredoc(解析变量,适合HTML片段) $html = <<<HTML <div class="user"><h3>{$name}</h3><p>年龄:25</p> </div> HTML;echo $html;// 4. nowdoc(不解析变量,类似单引号) $text = <<<'TEXT' 用户名:$name 这是一段不需要解析变量的文本 TEXT;echo $text; ?>
- 单引号:不解析变量和转义字符(除
常用字符串函数
- 长度与截取:
strlen()
(字节数)、mb_strlen()
(字符数,支持中文)、substr()
(截取)、mb_substr()
(多字节截取) - 查找与替换:
strpos()
(查找位置)、str_replace()
(替换)、preg_replace()
(正则替换) - 格式化:
trim()
(去除首尾空白)、strtolower()
(转小写)、strtoupper()
(转大写)、sprintf()
(格式化输出)
示例:
<?php $str = " Hello PHP8! "; $chinese = "PHP编程很有趣";// 1. 长度与截取 echo "strlen(英文):" . strlen($str) . "<br>"; // 输出:12(包含空格) echo "mb_strlen(中文):" . mb_strlen($chinese, "UTF-8") . "<br>"; // 输出:7(支持中文) echo "substr(截取):" . substr($str, 2, 5) . "<br>"; // 从第2个字符开始,截取5个:Hello echo "mb_substr(中文截取):" . mb_substr($chinese, 0, 3, "UTF-8") . "<br>"; // 输出:PHP// 2. 查找与替换 $pos = strpos($str, "PHP"); echo "PHP的位置:{$pos}<br>"; // 输出:7(从0开始计数) $new_str = str_replace("PHP8", "PHP7/8", $str); echo "替换后:{$new_str}<br>"; // 输出: Hello PHP7/8! // 3. 格式化 echo "trim(去除空格):'" . trim($str) . "'<br>"; // 输出:'Hello PHP8!' echo "strtolower(转小写):" . strtolower(trim($str)) . "<br>"; // 输出:hello php8! echo "sprintf(格式化):" . sprintf("%.2f", 123.456) . "<br>"; // 输出:123.46(保留2位小数) ?>
- 长度与截取:
正则表达式基础
- 用于复杂的字符串匹配、查找、替换
- PHP 中常用函数:
preg_match()
(匹配一次)、preg_match_all()
(匹配所有)、preg_replace()
(替换) - 常用正则模式:
\d
:匹配数字\w
:匹配字母、数字、下划线^
:匹配字符串开头$
:匹配字符串结尾{n,m}
:匹配 n 到 m 次
示例:
<?php // 1. 验证手机号(11位数字,以13/14/15/17/18开头) $phone = "13812345678"; $pattern = "/^1[34578]\d{9}$/"; if (preg_match($pattern, $phone)) {echo "手机号格式正确<br>"; } else {echo "手机号格式错误<br>"; }// 2. 提取字符串中的所有数字 $text = "PHP8发布于2020年,性能提升2-3倍"; preg_match_all("/\d+/", $text, $matches); print_r($matches[0]); // 输出:Array ( [0] => 8 [1] => 2020 [2] => 2 [3] => 3 )// 3. 替换敏感词(将"游戏"替换为"***") $content = "我喜欢玩游戏,尤其是竞技类游戏"; $sensitive = "/游戏/"; $filtered = preg_replace($sensitive, "***", $content); echo "过滤后:{$filtered}<br>"; // 输出:我喜欢玩***,尤其是竞技类*** ?>
三、注意事项
数组键名问题
- 避免使用浮点数作为数组键(会自动转为整数,如
$arr[2.5]
会变为$arr[2]
) - 关联数组的键名若为数字字符串(如
"123"
),会自动转为整数键 - 遍历数组时,关联数组建议用
foreach
,索引数组可用for
或foreach
- 避免使用浮点数作为数组键(会自动转为整数,如
中文字符串处理陷阱
strlen()
按字节计算长度(UTF-8 编码下中文占 3 字节),需用mb_strlen()
按字符计算substr()
不支持多字节字符(中文会乱码),需用mb_substr()
替代- 确保 PHP 配置文件中
mbstring
扩展已启用(默认启用)
正则表达式效率
- 复杂正则表达式会影响性能,简单匹配优先用字符串函数(如
strpos()
比preg_match()
快) - 避免过度使用通配符(如
.*
),尽量精确匹配(如[a-z0-9]+
) - 频繁使用的正则可先用
preg_quote()
处理特殊字符(如.
、*
等)
- 复杂正则表达式会影响性能,简单匹配优先用字符串函数(如
四、实战练习
创建
day5
文件夹,新建array_utils.php
文件:- 定义一个
ArrayUtils
类,包含以下静态函数:sortByKey(array $arr, string $key, string $order = "asc"): array
:对二维数组按指定键排序(asc
升序,desc
降序),使用 PHP7 太空船运算符groupByKey(array $arr, string $key): array
:对二维数组按指定键分组(如按role
分组用户)removeDuplicates(array $arr): array
:移除数组中的重复元素(支持关联数组,需保留首次出现的元素)
- 编写测试数据(如用户列表数组),验证每个函数的正确性
- 定义一个
新建
string_utils.php
文件:- 定义一个
StringUtils
类,包含以下静态函数:isEmail(string $email): bool
:验证邮箱格式(使用正则表达式)maskPhone(string $phone): string
:手机号脱敏(中间 4 位替换为****
,如138****5678
)countWords(string $text): int
:统计中文字符和英文单词个数(中文按字符计,英文按空格分隔的单词计)
- 编写测试用例,验证邮箱验证(正确 / 错误格式)、手机号脱敏、中英文混合文本的字数统计
- 定义一个