array_merge() 是 PHP 最常用的數組合併函數,但其對「數字鍵」與「字符串鍵」的不同處理邏輯常導致意外結果。本文通過實例詳細拆解其合併規則、鍵值衝突策略、邊界情況,並提供最佳實踐建議。
array_merge(array $array1, array ...$arrays): array
合併一個或多個數組,後者值追加到前者,返回新數組,不修改原數組。
<?php
$arr1 = ['astr1' => 'astr1', 3 => 'anum1'];
$arr2 = [
1 => 'bnum1', 2 => 'bnum2', 'bstr1' => 'bstr1',
3 => 'bnum3', 'astr1' => 'bstr2',
'0' => 'bstr3', '1' => 'bstr4'
];
print_r(array_merge($arr1, $arr2));
Array
(
[astr1] => bstr2 // 字符串鍵衝突:後者覆蓋前者
[0] => anum1 // 原 arr1[3] 重新索引為 0
[1] => bstr4 // 字符串鍵 '1' 視為數字鍵 1,覆蓋 arr2[1]='bnum1' 並重新索引
[2] => bnum2 // arr2[2] 重新索引
[bstr1] => bstr1 // 字符串鍵保持不變
[3] => bnum3 // 字符串鍵 '3' 視為字符串,不重新索引
[4] => bstr3 // 字符串鍵 '0' 視為數字鍵 0,重新索引為 4
)
| 鍵類型 | 合併行為 | 衝突處理 |
|---|---|---|
| 純數字字符串 ('0','1','123') | 視為數字鍵,重新從 0 遞增索引 | 後者值覆蓋前者同索引位置(因重新索引,實際為追加) |
| 非純數字字符串 ('3','01','1a') | 視為字符串鍵,保持原鍵名 | 後者覆蓋前者同名鍵 |
| 整數鍵 (0,1,2...) | 重新從 0 遞增索引 | 同上,實際為追加 |
| 字符串鍵 ('name','key') | 保持原鍵名 | 後者覆蓋前者 |
$a = ['0' => 'a', '1' => 'b'];
$b = ['1' => 'c', '2' => 'd'];
print_r(array_merge($a, $b));
// 結果: [0=>'a', 1=>'c', 2=>'d'] // '0','1' 變成 0,1 重新索引
對策:若需保留字符串鍵名,鍵名加前綴(如 'k_0')或改用 + 運算符。
+ 運算符與 array_merge 差異巨大$a = [0 => 'a', 1 => 'b'];
$b = [1 => 'c', 2 => 'd'];
var_dump($a + $b); // [0=>'a', 1=>'b', 2=>'d'] // 鍵不衝突則保留,衝突保留左側
var_dump(array_merge($a,$b)); // [0=>'a', 1=>'c', 2=>'d'] // 重新索引,後者覆蓋
選擇原則:保留鍵名關聯用 +;單純拼接數值索引數組用 array_merge。
array_merge([1,2], null); // Warning: Argument #2 must be of type array
對策:PHP 7.4+ 可用 array_merge([1,2], (array)$var) 強制轉換。
array_merge 創建新數組,大數組頻繁合併會產生大量內存分配。$result = []; foreach ($arrays as $arr) $result = array_merge($result, $arr); 或預分配大小 $result = array_merge(...$arrays)(PHP 7.4+ 解包)。$arr[] = $val 或 array_push 更高效。| 函數 | 鍵名處理 | 適用場景 |
|---|---|---|
| array_merge | 數字鍵重新索引,字符串鍵覆蓋 | 數值索引數組拼接、字符串鍵需後者優先 |
| array_merge_recursive | 同名鍵值合併為數組 | 多維配置合併、收集同名鍵所有值 |
| + 運算符 | 鍵名衝突保留左側,不重新索引 | 配置默認值覆蓋、保留原鍵關聯 |
| array_replace | 同名鍵後者覆蓋,不重新索引 | 關聯數組替換、遞歸替換用 array_replace_recursive |
array_merge 核心邏輯:數字鍵重排、字符串鍵覆蓋。理解「什麼是數字鍵」(整數或純數字字符串)是避坑關鍵。實際開發中,根據是否需要保留鍵名關聯,在 array_merge、+、array_replace 中選擇最語義化的函數。