主题
数组
数组用来在一个变量里存放一组值:一份名单、一组配置、一行数据库记录。PHP 的数组既能当「列表」(下标 0、1、2…),也能当「字典」(字符串当键)。保存为 arr.php 后执行 php arr.php:
php
<?php
$langs = ["PHP", "HTML", "SQL"];
echo $langs[0], "\n"; // PHP
$user = [
"name" => "小明",
"age" => 18,
];
echo $user["name"], "\n"; // 小明什么是数组
每个元素都有一个键(key)和一个值(value)。
- 索引数组:键是从
0起的整数,适合排队、列表 - 关联数组:键是字符串,适合「字段名 → 字段值」
两者在 PHP 里是同一种 array 类型,可以混用,但一个数组最好只选一种用法,读起来更清楚。
echo $langs 只会输出 Array,看不清内容。调试用 print_r() 或 var_dump():
php
<?php
$langs = ["PHP", "HTML"];
print_r($langs);
var_dump($langs);创建数组
现代 PHP 用短语法 [],不要再用老式的 array():
php
<?php
$empty = [];
$nums = [10, 20, 30];
$point = ["x" => 3, "y" => 5];最后一个元素后面可以留逗号(尾随逗号),改多行列表时更方便:
php
<?php
$colors = [
"red",
"green",
"blue",
];索引数组
不写键时,PHP 自动从 0 编号:
php
<?php
$langs = ["PHP", "HTML", "SQL"];
// 0 => "PHP"
// 1 => "HTML"
// 2 => "SQL"
echo $langs[1], "\n"; // HTML
echo count($langs), "\n"; // 3下标必须用方括号,不能写成 $langs.1。
可以只给部分元素指定整数键,后面未指定的会接着最大整数键往下排:
php
<?php
$nums = [2 => "a", "b", "c"];
print_r($nums);
// 2 => a, 3 => b, 4 => c初学不要依赖这种「自动接号」,需要连续下标就按顺序写入。
关联数组
键用 => 指向值。键通常是字符串:
php
<?php
$book = [
"title" => "PHP 基础",
"pages" => 120,
"done" => false,
];
echo $book["title"], "\n";键两边的引号不要省。未加引号的裸标识符会先被当成常量,PHP 8 里不存在该常量会报错。
键区分大小写:$book["Title"] 和 $book["title"] 不是同一个。
读取与修改
php
<?php
$langs = ["PHP", "HTML"];
$langs[1] = "CSS"; // 修改
echo $langs[1], "\n"; // CSS
$user = ["name" => "小明"];
$user["name"] = "小红";
$user["age"] = 18; // 原来没有这个键,等于新增PHP 8 读取不存在的键会 Warning,并当成 null:
php
<?php
$user = ["name" => "小明"];
echo $user["email"]; // Warning: Undefined array key "email"缺省值用 ??,不会报警:
php
<?php
$email = $user["email"] ?? "未填写";
echo $email, "\n";添加与删除
在列表末尾追加,推荐 $arr[] = 值:
php
<?php
$langs = ["PHP"];
$langs[] = "HTML";
$langs[] = "SQL";
print_r($langs); // PHP, HTML, SQLarray_push($langs, "HTML") 也能追加,追加一个元素时写 $langs[] = 更直接。
删除元素用 unset()。索引数组删掉中间项后,下标不会自动重排:
php
<?php
$langs = ["PHP", "HTML", "SQL"];
unset($langs[1]);
print_r($langs);
// 0 => PHP
// 2 => SQL 没有 1 了需要重新从 0 编号,用 array_values():
php
<?php
$langs = array_values($langs);
print_r($langs); // 0 => PHP, 1 => SQL整个变量删掉也是 unset($langs),和 变量定义 里一样。
键在不在
| 写法 | 含义 |
|---|---|
isset($arr["k"]) | 键存在,并且值不是 null |
array_key_exists("k", $arr) | 键存在,值是 null 也算 |
empty($arr["k"]) | 缺键、null、0、"" 等都算空,且不会因缺键报警 |
php
<?php
$user = ["name" => "小明", "bio" => null];
var_dump(isset($user["name"])); // true
var_dump(isset($user["bio"])); // false,值是 null
var_dump(array_key_exists("bio", $user)); // true
var_dump(isset($user["email"])); // false「有没有这个字段」用 array_key_exists;「有没有可用的值」用 isset。不要用 isset 去区分「没写」和「写了 null」,那时必须用 array_key_exists。isset / empty / is_null 总表见 内置函数。
遍历 foreach
遍历数组用 foreach,不必自己维护下标。循环篇里 先认识过,这里补全常用写法。
只要值:
php
<?php
$langs = ["PHP", "HTML", "SQL"];
foreach ($langs as $lang) {
echo $lang, "\n";
}键和值都要:
php
<?php
$user = ["name" => "小明", "age" => 18];
foreach ($user as $key => $value) {
echo "{$key}: {$value}\n";
}和 HTML 混写可用冒号语法:
php
<?php $langs = ["PHP", "HTML"]; ?>
<ul>
<?php foreach ($langs as $lang): ?>
<li><?= htmlspecialchars($lang, ENT_QUOTES, "UTF-8") ?></li>
<?php endforeach; ?>
</ul>用引用修改元素
默认 $value 是拷贝,改它不会写回数组。要在循环里改原数组,加 &,并在结束后 unset 掉引用:
php
<?php
$nums = [1, 2, 3];
foreach ($nums as &$n) {
$n *= 10;
}
unset($n);
print_r($nums); // 10, 20, 30漏掉 unset($n) 时,$n 仍引用最后一个元素,后面再给 $n 赋值会悄悄改掉数组。这是 PHP 里非常典型的坑,能不用引用就不用:用新数组收集结果往往更安全。
php
<?php
$nums = [1, 2, 3];
$scaled = [];
foreach ($nums as $n) {
$scaled[] = $n * 10;
}用 for 按下标遍历
连续整数下标时,for + count() 也可以:
php
<?php
$langs = ["PHP", "HTML", "SQL"];
for ($i = 0; $i < count($langs); $i++) {
echo $i, ": ", $langs[$i], "\n";
}count() 放进 for 的条件里,每轮都会算一遍。元素很多时先存起来:
php
<?php
$len = count($langs);
for ($i = 0; $i < $len; $i++) {
echo $langs[$i], "\n";
}关联数组、或中间缺了下标时,for 会漏元素或读到不存在的键。默认用 foreach。
嵌套数组
值也可以是数组,用来表示表格、树、一组记录:
php
<?php
$users = [
["name" => "小明", "age" => 18],
["name" => "小红", "age" => 20],
];
echo $users[0]["name"], "\n"; // 小明
foreach ($users as $user) {
echo $user["name"], "(", $user["age"], ")\n";
}一层一层用方括号往下取。深层键可能不存在时,PHP 7.4+ 可以用 nullsafe 之外的 ?? 链,或先判断:
php
<?php
$city = $users[0]["address"]["city"] ?? "未知";常用函数
记住这几个就够应付基础练习。
个数、是否包含:
php
<?php
$langs = ["PHP", "HTML", "SQL"];
echo count($langs), "\n"; // 3
var_dump(in_array("PHP", $langs, true)); // true,第三个参数 true 表示严格比较in_array 默认是 ==。查找时请传第三个参数 true,避免 in_array(0, ["foo"]) 这类宽松比较的坑。
键列表、值列表:
php
<?php
$user = ["name" => "小明", "age" => 18];
print_r(array_keys($user)); // name, age
print_r(array_values($user)); // 小明, 18拼接与拆分字符串:
php
<?php
$langs = ["PHP", "HTML", "SQL"];
echo implode(", ", $langs), "\n"; // PHP, HTML, SQL
$line = "php,html,sql";
$parts = explode(",", $line);
print_r($parts);排序(会改原数组):
php
<?php
$nums = [3, 1, 2];
sort($nums); // 按值排序,重排为连续索引
print_r($nums); // 1, 2, 3
$scores = ["a" => 90, "b" => 70, "c" => 80];
asort($scores); // 按值排序,保留键
ksort($scores); // 按键排序sort 会丢掉原来的字符串键,关联数组要用 asort / ksort。倒序对应 rsort / arsort / krsort。
合并与展开
array_merge 把多个数组接起来。数字键会重新编号,字符串键遇冲突时后面的覆盖前面的:
php
<?php
$a = ["PHP", "HTML"];
$b = ["SQL"];
print_r(array_merge($a, $b)); // PHP, HTML, SQL
$defaults = ["lang" => "zh", "theme" => "light"];
$custom = ["theme" => "dark"];
print_r(array_merge($defaults, $custom));
// lang => zh, theme => darkPHP 7.4+ 可用 ... 展开(更直观):
php
<?php
$all = [...$a, ...$b, "Git"];
print_r($all);运算符 + 也能合并,但左边已有的键不会被右边覆盖,数字键也不会重排。容易看错,本指南合并列表用 ... 或 array_merge。+、== / === 的细则见 数组运算符。
解包赋值
把数组里的值直接拆到变量里:
php
<?php
[$first, $second] = ["PHP", "HTML", "SQL"];
echo $first, " ", $second, "\n"; // PHP HTML
["name" => $name, "age" => $age] = ["name" => "小明", "age" => 18];
echo $name, "\n";交换两个变量也可以:[$a, $b] = [$b, $a];,在 变量定义 里提过。
常见误区
把数组当成字符串输出。 echo $arr 只会看到 Array。给用户看时先 implode,调试用 var_dump。
把 [] 和 {} 搞混。 取元素一律方括号 $arr["name"]。
foreach 引用忘记 unset。 见上文,优先用新数组收集。
用 == / in_array 默认模式比较。 数组里混了 0、"0"、false 时会误判,查找和比较都用严格模式。
假设 unset 之后下标是连续的。 需要连续索引时再 array_values。
在 for 里遍历关联数组。 缺键会 Warning,请改 foreach。
书写建议
- 新代码只用
[],关联数组键始终加引号 - 一个数组要么当列表,要么当字典,不要把
0和"name"混在同一层 - 读可能不存在的键用
??,不要直接取 - 遍历默认
foreach;追加默认$arr[] = $value in_array、array_search打开严格比较(第三个参数true)
练习
- 创建一个包含三门课程名的索引数组,用
foreach逐行输出;再追加第四门,输出count。 - 创建一个表示自己的关联数组(
name、lang、day),读取并拼成一句介绍;访问一个不存在的键时用??给出默认值。 - 二维数组保存两名用户的
name与age,遍历输出小明(18)这种格式。 - 用
implode把["a", "b", "c"]连成a-b-c;用explode再拆回去,print_r对照。