array_merge() 会重排所有整数键(含负数),从0开始连续编号,不保留原键;仅字符串键被保留。示例:[-1=>'x', -5=>'y']与[0=>'z']合并后为[0=>'x', 1=>'y', 2=>'z']。

PHP 8.3 中,负数索引数组用 array_merge() 合并后,下一个键不是 0,是因为 array_merge() 本身不保留负数键或非连续整数键——它只对“纯数字键”做重编号,且重编号逻辑是:清空所有整数键,从 0 开始连续分配,与原始键值正负无关。
简单说:负数键在 array_merge() 眼里,和 1、5、100 一样,都属于“要被扔掉重排”的数字键。 它不会因为你是 -1 就特殊照顾,也不会因为 -1 后面“理应接 0”就自动补上。
为什么负数键也会触发重编号?
- `array_merge()` 的判定标准只有一个:**键是否为 int 类型**(不是字符串 `' -1 '`,而是真正的整数 `-1`)。 - 只要任一输入数组中存在至少一个 int 键(比如 `-1`、`0`、`999`),整个结果数组的**所有 int 键都会被丢弃**,然后统一从 `0` 开始重新编号。 - 所以即使你传入 `[-1 => 'a', -2 => 'b']`,`array_merge()` 也会把它变成 `[0 => 'a', 1 => 'b']` —— 它根本不在乎你原来是不是负数,只认“这是整数键,得重排”。
示例:
```php $a = [-1 => 'x', -5 => 'y']; $b = [0 => 'z']; var_dump(array_merge($a, $b)); // 输出:array(3) { [0]=> string(1) "x" [1]=> string(1) "y" [2]=> string(1) "z" } ``` 注意:`-1` 和 `-5` 没有被保留,也没变成 `-1`, `0` 或 `-5`, `0`;它们直接消失,全部让位给 `0,1,2`。
那“下一个键为什么不是 0”其实是误解
这个提问隐含一个常见错觉:以为“负数索引数组合并后,会延续原有顺序,比如 `-1` 后面自然就是 `0`”。
但事实是:
- PHP 数组的键不是“序列地址”,而是独立存储的映射标识;
-
array_merge()的设计目标从来不是“延续索引”,而是“拼接值并重建顺序下标”; - 它不关心
-1后有没有0,也不检查键是否连续——它直接清空所有 int 键,再按值出现顺序从0逐个编号。
所以:
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- 原数组有
-100、-1、500?→ 全部无视,新数组键是0,1,2,...; - 原数组只有
[-1 => 'a']?→array_merge([-1=>'a'])结果仍是[0=>'a']; - 混合了字符串键?→ 字符串键照常保留,仅 int 键(含负数)被重排。
想保留负数键或自定义整数键?别用 array_merge()
如果你依赖 `-1`、`-100`、`999` 这类非标准索引,说明你把数字键当作了**语义标识**(比如表示状态码、偏移量、ID),而不是顺序位置。这时应换方法:
-
使用
+运算符(左侧优先,不重排,不覆盖同名 int 键):$a = [-1 => 'err']; $b = [0 => 'ok']; $result = $a + $b; // [-1=>'err', 0=>'ok'] — 键全部保留
-
使用
array_replace()(仅顶层替换,int 键按位置而非键名匹配):$a = [-1 => 'old']; $b = [-1 => 'new']; array_replace($a, $b); // [-1 => 'new'] — 键保留,值被替换
-
手动遍历赋值(完全可控):
$result = []; foreach ([$a, $b] as $arr) { foreach ($arr as $k => $v) { $result[$k] = $v; // 显式保留所有键 } }
小提醒:字符串数字键不受影响
- `' -1 '`、`'007'`、`'1e2'` 是字符串键,`array_merge()` 完全忽略它们,不会重排也不会报错; - 真正触发重编号的,只有 `int` 类型的键:`-1`、`0`、`42`、`PHP_INT_MIN` 都算。
不复杂但容易忽略。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










