前几篇讲完了变量、数据类型、流程控制和函数。但实际开发里,处理一批数据时单个变量根本不够用——学生名单、购物车商品、表单字段,这些都得靠数组。Web 开发里 80% 的活儿又都在处理字符串:用户输入清洗、URL 解析、内容搜索替换。这篇把数组和字符串的进阶用法一次讲透。写博客系统时,文章列表、标签云、用户评论、配置项——几乎每个功能都在跟"一组数据"打交道。把一组相关数据放进一个变量,这就是数组。标题、正文、摘要的清洗、截断、替换,全靠字符串函数。
除了前面用过的 array()和 [],还能用 range()、explode()快速生成数组。
<?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, ...]?>
数组里的元素也能是数组,形成多维结构,常用来表示表格数据或嵌套关系。
<?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]。
foreach 遍历多维数组:
<?php$matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9],];foreach($matrix as $row) { foreach($row as $cell) { echo $cell . " "; } echo "\n";}?>
老代码里常见的 while (list($k, $v) = each($arr))在 PHP 7.2+ 已弃用,直接用 foreach就行。
数组内部指针函数 current()、next()、prev()、end()、reset()能手动移动指针,现代 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个,插入新值?>
合并:
<?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$arr = [1, 2, 3, 4, 5];// 切片:从索引 1 开始取 3 个$slice = array_slice($arr, 1, 3); // [2,3,4](原数组不变)// 负数索引表示从末尾数$tail = array_slice($arr, -2); // [4,5]?>
示例:
<?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 引入的太空船运算符 <=>让比较更简洁:
usort($fruits, fn($a, $b) => strlen($a) <=> strlen($b));
array_map():对每个元素应用回调函数,返回新数组。
<?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$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$numbers = [1, 2, 3, 4];$sum = array_reduce($numbers, fn($carry, $item) => $carry + $item, 0); // 10?>
array_walk():对每个元素应用回调,直接修改原数组(返回 bool,不返回数组)。
<?php$fruits = ['apple', 'banana'];array_walk($fruits, function(&$value, $key) { $value = strtoupper($value);});// $fruits 变为 ['APPLE', 'BANANA']?>
PHP 预定义了几个在任何作用域都能访问的"超全局"数组,是脚本跟外部交互的通道。
<?php// $_GET:URL 查询字符串参数// URL:page.php?id=123&name=testecho $_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 或 POSTecho $_SERVER['REMOTE_ADDR']; // 客户端 IPecho $_SERVER['HTTP_USER_AGENT'];// $_FILES:上传文件信息(下一篇详细讲)// $_SESSION:会话变量(需 session_start())// $_COOKIE:HTTP Cookie// $_ENV:环境变量?>
安全提醒:永远不要直接信任 $_GET、$_POST里的数据,使用前必须过滤和验证。正则表达式是字符串匹配和替换的利器。PHP 用 PCRE(Perl 兼容正则)函数族,都以 preg_开头。
基础语法:
preg_match():匹配一次,返回 0/1,匹配结果存入第三个参数。
<?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$text = "电话: 13800138000, 还有 15912345678";preg_match_all("/\d{11}/", $text, $matches);print_r($matches[0]); // [13800138000, 15912345678]?>
preg_replace():查找并替换。
<?php$str = "Hello, 2026!";$cleaned = preg_replace("/\d+/", "XXXX", $str);echo $cleaned; // "Hello, XXXX!"?>
preg_split():按模式分割字符串。
<?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}$/
正则需要多练才能熟练,但掌握基本语法就够应付多数场景。
处理中文等非英文字符时,必须用 mb_开头的多字节字符串函数,否则会得到错误结果。
<?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");
<?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)*/?>
除了 explode和 implode,还有更灵活的 str_split和 preg_split。
<?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"]?>
<?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"?>
<?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第二行");?>
把数组和字符串函数结合起来,做一个命令行下的"词频统计器"——读取一段文本,统计每个单词出现次数并排序输出。
<!DOCTYPE html><htmllang="zh-CN"><head> <metacharset="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><divclass="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> <thwidth="12%">排名</th> <thwidth="60%">单词</th> <thwidth="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 函数、格式化输出。
本文基于作者实际学习与项目经验整理,代码示例均经本地测试。文字整理过程中借助了 AI 工具辅助排版。
如果这篇解决了你的问题,欢迎关注「云水一下」,后续遇到类似报错可以直接翻历史消息找。