PHP数组操作核心在于场景化选函数:foreach引用后须unset防污染;+与array_merge行为迥异;查键用isset或array_key_exists;删值优先array_diff,删条件元素用array_filter。

PHP数组操作的核心不是记住所有函数,而是知道在什么场景下用哪个函数、为什么不能乱换、以及哪几个细节一错就报错或丢数据。
遍历数组时,foreach 用引用要手动 unset
直接写 foreach ($arr as &$value) 确实能原地改值,但 PHP 会把最后一个 $value 的引用留在作用域里——下次再用同名变量,可能意外改到前一次的数组元素。这不是 bug,是语言机制。
必须配对写:unset($value),哪怕只是加在循环末尾一行。不写的话,下面这段代码会出问题:
foreach ($arr as &$v) {
$v = strtoupper($v);
}
unset($v); // 必须有
// 后续若再 foreach ($arr as $v) { ... },$v 就不会被污染
如果只读,就别加 &;需要键值一起处理,用 foreach ($arr as $k => $v) 更安全。
立即学习“PHP免费学习笔记(深入)”;
合并两个数组,+ 和 array_merge() 行为完全不同
$a + $b 是「左优先」合并:保留 $a 的键,$b 中相同键名的值被忽略;数字键不重排,关联键也不覆盖。
array_merge($a, $b) 是「后覆盖」合并:字符串键以 $b 为准,数字键强制重索引(0,1,2…),哪怕 $a 原来是 [0=>'x', 2=>'y'],合并后也会变成 [0=>'x', 1=>'y', ...]。
常见误用场景:
- 想合并配置项且保留
$default的键结构 → 用$default + $user - 想把两个索引数组拼成一个连续列表 → 用
array_merge($a, $b) - 想合并关联数组并让
$b覆盖$a→ 用array_merge($a, $b),但注意数字键会丢
查键是否存在,别用 in_array() 判 key
in_array('foo', $arr) 是查值,时间复杂度 O(n),大数组很慢;而且它还会触发类型宽松比较(比如 0 == 'abc' 可能为 true)。
查键是否存在,该用:
-
isset($arr['key']):快,但若$arr['key'] === null,返回 false -
array_key_exists('key', $arr):严格判断键是否存在,null 值也返回 true
查值存在且要高性能?先 $flip = array_flip($arr),再 isset($flip[$search]) —— 把 O(n) 降到 O(1),前提是值唯一或你接受后出现的覆盖前出现的。
删指定值的所有元素,array_diff() 比循环更稳
很多人写循环找 key 再 unset,容易漏掉重复值、键不连续、或忘记重索引。其实最简方案是:
$arr = array_diff($arr, ['target_value']);
它保留原始键名,不重排索引,也不会因键不存在报 notice。如果后续要数字索引,再套一层 array_values($arr)。
注意:array_diff() 比较是松散的(0 == '0'),要严格比较得用 array_diff_assoc() 或自己写回调。
真正难的是删「满足某条件」的元素——这时候该上 array_filter($arr, $callback),而不是硬写 foreach + unset。



















