摘要 :在前几篇中,我们已经掌握了变量、数据类型、流程控制和函数,但你是否发现,当需要处理一批数据时(如学生名单、购物车商品、表单提交的多个字段),单个变量就显得力不从心了。数组正是为了解决"批量数据"而生,它是 PHP 中最强大、最灵活的数据结构。与此同时,Web 开发中 80% 的工作都在处理字符串------从用户输入的清洗、URL 解析,到内容搜索替换。本篇将带你深入数组的创建、遍历、排序、合并与切片,掌握常用的回调函数(array_map、array_filter),并揭秘 $_GET、$_POST、$_SERVER 等超全局数组。在字符串部分,我们将进阶学习正则表达式入门、URL 与 HTML 处理、多字节字符串以及各种实用格式化函数。
一、引言:为什么数组和字符串如此重要?
设想你正在开发一个博客系统。文章列表、标签云、用户评论、配置项......几乎每一个功能都需要与"一组数据"打交道。把一组相关的数据放在一个变量中,这就是数组。而标题、正文、摘要、URL 的清洗、截断、替换,全离不开字符串函数。
二、数组进阶:从基本操作到数据处理
2.1 数组的创建方式
除了前面学过的 array() 和 [],还可以通过 range()、explode() 等函数快速生成数组。
php
<?php
// 使用 range 生成连续数组
$numbers = range(1, 10); // [1,2,...,10]
$letters = range('a', 'z'); // ['a','b',...,'z']
$even = range(0, 20, 2); // 步长为 2
// 使用 explode 从字符串生成数组(回顾第二篇)
$tags = "php,mysql,html,css";
$tagArray = explode(",", $tags);
// 使用 array_combine 合并键和值数组
$keys = ['name', 'age', 'city'];
$values = ['张三', 25, '上海'];
$info = array_combine($keys, $values); // ['name'=>'张三', 'age'=>25, ...]
?>
2.2 多维数组
数组中的元素也可以是数组,形成多维数组,常用于表示表格数据或嵌套结构。
php
<?php
$students = [
["张三", 22, "计算机系"],
["李四", 23, "数学系"],
["王五", 21, "物理系"],
];
// 关联数组嵌套
$users = [
"u01" => ["name" => "Alice", "email" => "alice@example.com"],
"u02" => ["name" => "Bob", "email" => "bob@example.com"],
];
echo $users["u01"]["name"]; // Alice
?>
多维数组的访问通过连续索引 [键1][键2]。
2.3 数组的遍历与迭代器
foreach 遍历多维数组:
php
<?php
$matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
foreach ($matrix as $row) {
foreach ($row as $cell) {
echo $cell . " ";
}
echo "\n";
}
?>
使用 each() 和 list()(PHP 7.2+ each 已弃用,改用 foreach) : 老代码中常出现 while (list($k, $v) = each($arr)),现在直接用 foreach 即可。
数组内部指针 :current()、next()、prev()、end()、reset() 可手动移动数组内部指针,但在现代 PHP 中较少使用,了解即可。
2.4 数组元素增删改
php
<?php
$arr = ['a', 'b', 'c'];
// 末尾添加
array_push($arr, 'd'); // 返回新长度,也相当于 $arr[] = 'd';
$arr[] = 'e'; // 更简洁,推荐
// 开头添加
array_unshift($arr, 'x'); // 返回新长度
// 末尾删除
$last = array_pop($arr); // 返回移除的元素
// 开头删除
$first = array_shift($arr); // 返回移除的元素
// 指定位置插入(无直接函数,使用 array_splice)
array_splice($arr, 2, 0, 'inserted'); // 索引2位置插入,不删除任何元素
// 删除指定元素(根据值)
$arr = array_diff($arr, ['b']); // 删除所有值为 'b' 的元素
// 删除并替换(用 array_splice)
$removed = array_splice($arr, 1, 2, ['new1', 'new2']); // 从索引1开始删2个,插入新值
?>
2.5 数组的合并与切片
合并:
php
<?php
$a = [1, 2, 3];
$b = [4, 5, 6];
$c = array_merge($a, $b); // [1,2,3,4,5,6]
// 关联数组合并,相同键后者覆盖前者
$x = ['name' => '张三', 'age' => 20];
$y = ['age' => 25, 'city' => '上海'];
$z = array_merge($x, $y); // ['name'=>'张三', 'age'=>25, 'city'=>'上海']
// + 运算符也可以合并,但相同键保留前者
$z2 = $x + $y; // ['name'=>'张三', 'age'=>20, 'city'=>'上海']
?>
切片 :array_slice() 不改变原数组,array_splice() 会修改原数组。
php
<?php
$arr = [1, 2, 3, 4, 5];
// 切片:从索引 1 开始取 3 个
$slice = array_slice($arr, 1, 3); // [2,3,4](原数组不变)
// 负数索引表示从末尾数
$tail = array_slice($arr, -2); // [4,5]
?>
2.6 数组排序详解
| 函数 | 排序方式 | 是否保留键名 | 说明 |
|---|---|---|---|
| sort() | 升序(重置键名) | 否 | 索引数组排序 |
| rsort() | 降序(重置键名) | 否 | |
| asort() | 按值升序 | 是 | 关联数组按值排序 |
| arsort() | 按值降序 | 是 | |
| ksort() | 按键升序 | 是 | 按键名排序 |
| krsort() | 按键降序 | 是 | |
| usort() | 用户自定义比较函数 | 否 | 自定义排序逻辑 |
| uasort() | 用户自定义比较函数 | 是 | 按值自定义排序 |
| uksort() | 用户自定义比较函数 | 是 | 按键自定义排序 |
示例:
php
<?php
$fruits = ['orange', 'apple', 'banana'];
sort($fruits); // ['apple','banana','orange']
$scores = ['张三' => 85, '李四' => 92, '王五' => 78];
asort($scores); // 按分数升序:王五、张三、李四
ksort($scores); // 按键名升序:张三(张的拼音靠后,看字符编码)
// 自定义排序:按字符串长度
usort($fruits, function($a, $b) {
return strlen($a) - strlen($b);
});
?>
usort 的比较函数应返回整数:<0 表示 $a 小于 $b,0 表示相等,>0 表示 $a 大于 $b。PHP 7 引入了"太空船运算符" <=>,让比较更简洁:
php
usort($fruits, fn($a, $b) => strlen($a) <=> strlen($b));
2.7 数组的回调函数:数据处理的利器
array_map():对数组的每个元素应用回调函数,返回新数组。
php
<?php
$numbers = [1, 2, 3, 4, 5];
$squared = array_map(function($n) { return $n * $n; }, $numbers);
// [1, 4, 9, 16, 25]
// 可传入多个数组
$a = [1, 2, 3];
$b = [4, 5, 6];
$sum = array_map(fn($x, $y) => $x + $y, $a, $b); // [5, 7, 9]
?>
array_filter():使用回调过滤元素,返回满足条件的元素数组。
php
<?php
$numbers = [1, 2, 3, 4, 5, 6];
$even = array_filter($numbers, fn($n) => $n % 2 == 0);
// [1=>2, 3=>4, 5=>6] (键名保留)
// 若想重置索引,用 array_values($even)
?>
array_reduce():将数组迭代归约为单一值(如求和、乘积、拼接字符串)。
php
<?php
$numbers = [1, 2, 3, 4];
$sum = array_reduce($numbers, fn($carry, $item) => $carry + $item, 0); // 10
?>
array_walk():对数组每个元素应用回调,直接修改原数组(返回 bool,不返回数组)。
php
<?php
$fruits = ['apple', 'banana'];
array_walk($fruits, function(&$value, $key) {
$value = strtoupper($value);
});
// $fruits 变为 ['APPLE', 'BANANA']
?>
2.8 其他实用数组函数速览
-
in_array($value, $array):检查值是否存在。 -
array_key_exists($key, $array):检查键是否存在。 -
array_search($value, $array):搜索值,返回对应键名。 -
array_keys($array):返回所有键名。 -
array_values($array):返回所有值,重建索引。 -
array_unique($array):移除重复值。 -
array_reverse($array):反转数组顺序。 -
array_rand($array, $num):随机取出一个或多个键。 -
shuffle($array):打乱数组(键名丢失)。 -
array_sum($array):计算数组所有值的和。 -
array_count_values($array):统计每个值出现的次数。
2.9 超全局数组:Web 开发的接口
PHP 预定义了几个在任何作用域都可访问的"超全局"数组,它们是脚本与外部交互的通道。
php
<?php
// $_GET:URL 查询字符串参数
// URL:page.php?id=123&name=test
echo $_GET['id']; // 123
// $_POST:HTTP POST 方法提交的数据
echo $_POST['username'];
// $_REQUEST:合并了 $_GET、$_POST、$_COOKIE(不推荐使用,来源不清)
// $_SERVER:服务器和执行环境信息
echo $_SERVER['HTTP_HOST']; // 当前请求的主机名
echo $_SERVER['REQUEST_URI']; // 请求的 URI(不含主机)
echo $_SERVER['REQUEST_METHOD'];// GET 或 POST
echo $_SERVER['REMOTE_ADDR']; // 客户端 IP
echo $_SERVER['HTTP_USER_AGENT'];
// $_FILES:上传文件信息(下一篇详细讲)
// $_SESSION:会话变量(需 session_start())
// $_COOKIE:HTTP Cookie
// $_ENV:环境变量
?>
安全性提示 :永远不要信任 $_GET、$_POST 中的数据,使用前务必进行过滤和验证(后续篇章会详细展开)。
三、字符串操作进阶:正则与多字节
3.1 正则表达式入门
正则表达式是字符串匹配和替换的"瑞士军刀"。PHP 使用 PCRE(Perl 兼容正则)函数族,以 preg_ 开头。
① 基础模式
-
/pattern/定界符,常用/。 -
^开头,$结尾。 -
.任意字符,*零次或多次,+一次或多次,?零次或一次。 -
\d数字,\w单词字符,\s空白。 -
[abc]字符集,[a-z]范围,[^abc]非字符集。 -
{n,m}出现 n 到 m 次。 -
修饰符:
i(不区分大小写),m(多行模式),u(UTF-8 模式)。
② preg_match():匹配一次,返回 0/1,并将匹配结果存入第三个参数。
php
<?php
$email = "user@example.com";
$pattern = "/^[\w\.-]+@[\w\.-]+\.\w{2,}$/";
if (preg_match($pattern, $email, $matches)) {
echo "邮箱合法: " . $matches[0];
} else {
echo "邮箱非法";
}
?>
③ preg_match_all():全局匹配,返回匹配次数。
php
<?php
$text = "电话: 13800138000, 还有 15912345678";
preg_match_all("/\d{11}/", $text, $matches);
print_r($matches[0]); // [13800138000, 15912345678]
?>
④ preg_replace():查找并替换。
php
<?php
$str = "Hello, 2026!";
$cleaned = preg_replace("/\d+/", "XXXX", $str);
echo $cleaned; // "Hello, XXXX!"
?>
⑤ preg_split():按模式分割字符串。
php
<?php
$data = "apple, banana; orange | pineapple";
$fruits = preg_split("/[,;|]\s*/", $data);
// ["apple", "banana", "orange", "pineapple"]
?>
⑥ 常见正则示例:
-
手机号(中国大陆):
/^1[3-9]\d{9}$/ -
URL:
/https?:\/\/[\w\-]+(\.[\w\-]+)+([\w\-\.,@?^=%&:/~+#]*)?/ -
日期格式 YYYY-MM-DD:
/^\d{4}-\d{2}-\d{2}$/
正则表达式需要多加练习才能熟练,但掌握基本语法就足以应对多数场景。
3.2 多字节字符串处理
在处理中文等非英文字符时,必须使用 mb_ 开头的多字节字符串函数,否则会得到错误结果。
php
<?php
$cn = "你好世界";
echo strlen($cn); // 12(UTF-8 下每个汉字 3 字节)
echo mb_strlen($cn); // 4 (正确字符数)
echo substr($cn, 0, 3); // 可能输出乱码
echo mb_substr($cn, 0, 2); // "你好"
echo mb_strpos($cn, "世界"); // 2(从 0 开始)
?>
常用 mb_ 函数:mb_strlen、mb_substr、mb_strpos、mb_strtolower、mb_strtoupper、mb_convert_encoding、mb_convert_case 等。
设置内部编码 (在脚本开头或 php.ini 中):mb_internal_encoding("UTF-8");
3.3 URL 与 HTML 相关函数
php
<?php
// URL 编码与解码
$query = "name=张三&age=25";
$encoded = urlencode($query); // name=%E5%BC%A0%E4%B8%89...
echo urldecode($encoded); // 还原
// HTTP 构建查询字符串
$data = ['name' => '张三', 'age' => 25];
echo http_build_query($data); // name=%E5%BC%A0%E4%B8%89&age=25
// 解析 URL
$url = "https://user:pass@example.com:8080/path?id=1#frag";
$parts = parse_url($url);
print_r($parts);
/*
Array (
[scheme] => https
[host] => example.com
[user] => user
[pass] => pass
[path] => /path
[query] => id=1
[fragment] => frag
)
*/
?>
3.4 字符串与数组的深度互转
除了 explode 和 implode,还有更灵活的 str_split 和 preg_split。
php
<?php
// 按字符分割(包括多字节慎用,最好用 mb_str_split PHP 7.4+)
$chars = str_split("Hello", 2); // ['He','ll','o']
// 利用正则分割,保留分隔符
$str = "apple, banana, orange";
$parts = preg_split("/(,\s*)/", $str, -1, PREG_SPLIT_DELIM_CAPTURE);
// ["apple", ", ", "banana", ", ", "orange"]
?>
3.5 字符串搜索与高级替换
php
<?php
$text = "Hello World, Hello PHP";
// str_replace(基本替换)
$replaced = str_replace("Hello", "你好", $text);
// str_ireplace(不区分大小写)
$replaced = str_ireplace("hello", "你好", $text);
// strtr() 按字符映射替换
echo strtr("abc", "a", "x"); // "xbc"
echo strtr("abc", ["a"=>"x"]); // "xbc"
// strpos/stripos 查找位置,stripos 不区分大小写
$pos = strpos($text, "World"); // 6
// strstr/stristr 查找子串并返回从该位置到结尾的字符串
$rest = strstr($text, "World"); // "World, Hello PHP"
// strrchr 从最后出现的位置开始返回
echo strrchr("file.txt.zip", "."); // ".zip"
?>
3.6 格式化输出函数
php
<?php
// printf 系列:格式化字符串并输出/返回
$price = 9.99;
printf("价格:%.2f 元", $price); // 直接输出
$formatted = sprintf("价格:%.2f 元", $price); // 返回字符串
// number_format() 千位分隔与小数
echo number_format(1234567.89, 2, '.', ','); // 1,234,567.89
// str_pad 填充
echo str_pad("5", 3, "0", STR_PAD_LEFT); // 005
// nl2br 换行符转 <br>
echo nl2br("第一行\n第二行");
?>
四、综合实战:编写一个简单的文本数据处理工具
让我们结合数组和字符串函数,制作一个命令行下的"词频统计器"。读取一段文本,统计每个单词出现的次数并排序输出。
php
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>英文词频统计工具</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Microsoft YaHei", sans-serif;
}
body {
background-color: #f4f7fc;
padding: 40px;
}
.container {
max-width: 700px;
margin: 0 auto;
background: #fff;
padding: 30px;
border-radius: 12px;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}
h1 {
text-align: center;
color: #2c3e50;
margin-bottom: 25px;
font-size: 24px;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #e2e8f0;
}
th {
background-color: #3498db;
color: white;
}
tr:nth-child(even) {
background-color: #f8fafc;
}
.count-high {
color: #e74c3c;
font-weight: bold;
}
</style>
</head>
<body>
<div class="container">
<h1>📖 英文文本词频统计 TOP10</h1>
<?php
/**
* 简易英文词频统计器
* 输入一段英文文本,返回按单词出现频次降序的数组
* @param string $text 原始英文文本
* @param int $minLength 单词最小长度,默认2
* @return array [单词 => 出现次数]
*/
function wordFrequency(string $text, int $minLength = 2): array {
// 全部转为小写
$text = mb_strtolower($text);
// 替换所有标点、特殊符号为空格,保留字母与连字符(复合单词)
$text = preg_replace("/[^a-z\s\-]/", " ", $text);
// 多个连续空格统一替换为单个空格
$text = preg_replace("/\s+/", " ", trim($text));
// 按空格分割单词,过滤空元素
$words = explode(" ", $text);
// 过滤长度不足的单词
$words = array_filter($words, function ($word) use ($minLength) {
return mb_strlen($word) >= $minLength;
});
// 统计每个单词出现次数
$frequency = array_count_values($words);
// 按频次降序排序
arsort($frequency);
return $frequency;
}
// 测试示例文本
$sample = "PHP is a popular general-purpose scripting language that is especially suited to web development. Fast, flexible and pragmatic, PHP powers everything from your blog to the most popular websites in the world.";
// 获取词频结果
$result = wordFrequency($sample);
?>
<table>
<tr>
<th width="12%">排名</th>
<th width="60%">单词</th>
<th width="28%">出现次数</th>
</tr>
<?php
$rank = 1;
foreach ($result as $word => $count) {
// 出现2次及以上标红加粗
$countClass = $count >= 2 ? 'count-high' : '';
echo <<<TR
<tr>
<td>{$rank}</td>
<td>{$word}</td>
<td class="{$countClass}">{$count}</td>
</tr>
TR;
if ($rank >= 10) break;
$rank++;
}
?>
</table>
</div>
</body>
</html>

这个程序用到了正则替换和分割、数组过滤、array_count_values、arsort、printf 等,正是本系列知识的集中运用。
五、总结
-
数组高级操作:创建(range/explode)、多维数组、增删改(push/pop/shift/unshift/splice)、合并与切片(merge/slice)、各种排序及自定义排序(usort)、回调函数(map/filter/reduce/walk)。
-
超全局数组 :
$_GET、$_POST、$_SERVER等是 Web 与 PHP 的核心交互接口。 -
字符串进阶:正则表达式入门(preg_match/match_all/replace/split)、多字节字符串(mb_* 系列)、URL 与 HTML 函数、格式化输出。
如果这篇文章帮你解决了实操上的困惑,别忘记点击点赞、分享 ,也可以留言告诉我你遇到的其它问题,我会尽快回复。动手练习是掌握编程最快的方法,请务必亲手敲一遍本文的所有示例代码,并截图保存你的成果。你的关注是我坚持原创和细节共享的力量来源,谢谢大家。