PHP 8.1+ 支持变量数组首层解包(如[...$a, ...$b]),但仅一维展开、重置键名;PHP 7.4–8.0 仅支持字面量或可遍历表达式解包,变量需用array_merge()或+运算符替代。

PHP 7.4+ 支持数组解包(...),但仅限于「字面量数组」或「可遍历表达式」,不能直接解包变量数组——除非你用的是 PHP 8.1+ 的「首层解包」语法;否则老版本必须用 array_merge() 或 [...$arr1, ...$arr2](PHP 8.1+)。
PHP 8.1+ 直接解包变量数组
PHP 8.1 起允许对变量数组使用 ... 解包(称为“首层解包”),前提是该变量是数组或实现了 Traversable 的对象:
$a = [1, 2]; $b = [3, 4]; $result = [...$a, ...$b]; // [1, 2, 3, 4]
- 只支持一维展开,嵌套数组不会递归解包
- 键名会被重置为数字索引(即“数值键重排”),关联键会丢失
- 若需保留关联键,不能用解包,得改用
array_merge() - 解包时若某变量不是数组或可遍历对象,会抛出
Fatal error: Uncaught TypeError
PHP 7.4–8.0 只能解包字面量或表达式
在 PHP 7.4 到 8.0 中,... 只接受「字面量数组」或「返回数组的函数调用」,不接受普通变量:
// ✅ 合法(字面量)
$result = [...[1, 2], ...[3, 4]];
// ✅ 合法(函数返回数组)
function getItems() { return ['x', 'y']; }
$result = [...getItems(), ...[1, 2]];
// ❌ 致命错误:Cannot use (...) on a variable
$a = [1, 2]; $result = [...$a];
- 常见误写:
[...$arr]在 PHP 8.0 及以下直接报错,不是警告 - 临时绕过:用
array_merge([], $arr1, $arr2)替代,兼容所有 PHP 5.6+ -
array_merge()对数字键会重排,对字符串键会覆盖(后出现的同名键胜出)
保留键名?别用解包,用 array_merge 或 +
如果数组含字符串键(如配置项、映射表),且需要保留或合并逻辑,解包完全不合适:
立即学习“PHP免费学习笔记(深入)”;
$conf1 = ['host' => 'localhost', 'port' => 3306]; $conf2 = ['port' => 3307, 'user' => 'root']; // ❌ 解包会丢键、变数字索引 var_dump([...$conf1, ...$conf2]); // [0=>'localhost', 1=>3306, 2=>3307, 3=>'root'] // ✅ array_merge:后键覆盖前键 var_dump(array_merge($conf1, $conf2)); // ['host'=>'localhost','port'=>3307,'user'=>'root'] // ✅ + 运算符:前键优先,不覆盖 var_dump($conf1 + $conf2); // ['host'=>'localhost','port'=>3306,'user'=>'root']
-
array_merge()和+行为相反:前者“后赢”,后者“前赢” -
+不会重排数字键,但会忽略重复数字键(只留左边的) - 混合键类型时,
array_merge()更可预测;+易因键顺序产生歧义
性能与实际选型建议
解包语法看着简洁,但实际性能并不比 array_merge() 好——尤其在大数组场景下,PHP 8.1+ 的解包仍需复制值,且无引用优化:
- 小数组([...$a, ...$b] 更直观
- 中大数组或需保留键:坚持用
array_merge(),明确语义且全版本兼容 - 要避免意外重排数字键?用
array_replace()或手动foreach合并 - 别在循环里反复解包:每次都会新建数组,GC 压力明显上升
真正容易被忽略的是键名语义——很多人图快写 [...$a, ...$b],结果发现配置里的 'timeout' 被覆盖了却没意识到,因为没检查键冲突。解包只管结构,不管业务含义。



















