Skip to content

数组

数组用来在一个变量里存放一组值:一份名单、一组配置、一行数据库记录。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, SQL

array_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"])缺键、null0"" 等都算空,且不会因缺键报警
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_existsisset / 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 => dark

PHP 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_arrayarray_search 打开严格比较(第三个参数 true

练习

  1. 创建一个包含三门课程名的索引数组,用 foreach 逐行输出;再追加第四门,输出 count
  2. 创建一个表示自己的关联数组(namelangday),读取并拼成一句介绍;访问一个不存在的键时用 ?? 给出默认值。
  3. 二维数组保存两名用户的 nameage,遍历输出 小明(18) 这种格式。
  4. implode["a", "b", "c"] 连成 a-b-c;用 explode 再拆回去,print_r 对照。

上一篇:循环
下一篇:数组运算符

基于 VitePress 构建的 PHP 基础学习指南