array_merge() 是 PHP 合併陣列的核心函數,但其對**字串鍵**與**數值鍵**的處理邏輯截然不同,誤用易導致資料遺失或索引錯亂。本文詳細解析並提供最佳實務。
| 鍵型別 | array_merge 行為 | array_merge_recursive 行為 |
|---|---|---|
| 字串鍵 (關聯陣列) | **後者覆蓋前者** | **遞迴合併**,同鍵值變為陣列 |
| 數值鍵 (索引陣列) | **重新編號從 0 開始**,依序附加 | 同 array_merge(數值鍵不遞迴) |
<?php
$book1 = ['linux' => 'Linux 伺服器設定', 'php' => 'PHP 程式設計'];
$book2 = ['linux' => '伺服器管理實戰', 'jsp' => 'JSP 開發'];
print_r(array_merge($book1, $book2));
/* 輸出:
Array
(
[linux] => 伺服器管理實戰 // 被覆蓋
[php] => PHP 程式設計
[jsp] => JSP 開發
)
*/
print_r(array_merge_recursive($book1, $book2));
/* 輸出:
Array
(
[linux] => Array
(
[0] => Linux 伺服器設定
[1] => 伺服器管理實戰
)
[php] => PHP 程式設計
[jsp] => JSP 開發
)
*/
?>
<?php
$arr1 = ['Linux 伺服器設定', 'PHP 程式設計'];
$arr2 = ['伺服器管理實戰', 'JSP 開發'];
print_r(array_merge($arr1, $arr2));
/* 輸出:
Array
(
[0] => Linux 伺服器設定
[1] => PHP 程式設計
[2] => 伺服器管理實戰
[3] => JSP 開發
)
索引重新從 0 連續編號
*/
?>
<?php
$a = [0 => 'a', 'x' => ['a1', 'a2'], 1 => 'b'];
$b = [0 => 'c', 'x' => ['b1'], 'y' => 'y1'];
print_r(array_merge($a, $b));
/* 輸出:
Array
(
[0] => a
[x] => Array ( [0] => b1 ) // 字串鍵 'x' 被覆蓋,原陣列遺失
[1] => b
[2] => c // 數值鍵重新編號
[y] => y1
)
*/
?>
<?php
$arr1 = [5 => 'a', 6 => 'b'];
$arr2 = [7 => 'c', 8 => 'd'];
$result = $arr1 + $arr2; // [5=>'a', 6=>'b', 7=>'c', 8=>'d'] 索引不變
?>
<?php
function array_merge_deep(array ...$arrays): array {
$result = [];
foreach ($arrays as $arr) {
foreach ($arr as $key => $value) {
if (is_int($key)) {
$result[] = $value; // 數值鍵重新編號
} elseif (isset($result[$key]) && is_array($result[$key]) && is_array($value)) {
$result[$key] = array_merge_deep($result[$key], $value); // 遞迴
} else {
$result[$key] = $value; // 字串鍵覆蓋
}
}
}
return $result;
}
?>
成熟框架提供更語意化的合併方法(如 Arr::mergeRecursiveDistinct),專案若引用框架請優先使用。
array_merge(需重新編號)或 +(保留索引)。array_merge。array_merge_recursive 或自訂深度合併。理解鍵型別差異,避免「莫名其妙資料不見」的經典坑。