PHP 數組添加元素完全指南:8 種方法、性能基準、陷阱避坑、現代最佳實踐
方法總覽速查表
| 方法 | 語法 | 位置 | 鍵類型 | 性能 | 推薦指數 |
| [] 短語法 | $arr[] = $val | 尾部 | 自動數字索引 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ 首選 |
| array_push() | array_push($arr, $v1, $v2...) | 尾部 | 自動數字索引 | ⭐⭐⭐⭐ | ⭐⭐⭐ 批量追加 |
| 指定鍵賦值 | $arr['key'] = $val | 任意 | 字符串/數字 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ 關聯數組首選 |
| array_unshift() | array_unshift($arr, $v1, $v2...) | 頭部 | 重建 0 索引 | ⭐⭐⭐ | ⭐⭐ 隊列入隊 |
| array_merge() | array_merge([$k=>$v], $arr) | 頭部 | 保留字符串鍵 | ⭐⭐ | ⭐⭐ 合併場景 |
| + 聯合運算符 | [$k=>$v] + $arr | 頭部 | 保留字符串鍵、不覆蓋 | ⭐⭐⭐ | ⭐⭐⭐ 默認值合併 |
| array_splice() | array_splice($arr, 0, 0, [$v]) | 任意 | 重建數字索引 | ⭐⭐ | ⭐ 插入中間 |
| [] 指定數字索引 | $arr[5] = $val | 指定位置 | 數字索引 | ⭐⭐⭐⭐ | ⭐⭐⭐ 稀疏數組 |
詳細解析與代碼示例
1. [] 短語法 —— 尾部追加王者
$arr = ['a', 'b'];
$arr[] = 'c'; // ['a','b','c']
$arr[] = 'd'; // ['a','b','c','d']
// 等價於 array_push($arr, 'c', 'd') 但更快、更簡潔
// 原理:直接使用 nNextFreeElement 內部計數器,O(1) 寫入
- PHP 內核優化:
$arr[] 直接映射為 ZEND_HASH_NEXT_INSERT,無函數調用開銷
- 單次追加首選;批量追加用
array_push($arr, ...$values)(PHP 7.3+ 支援展開操作符)
2. array_push() —— 批量追加、返回新長度
$arr = ['a', 'b'];
$len = array_push($arr, 'c', 'd', 'e'); // $len = 5
// 返回新元素個數,便於即時獲取長度
// 注意:第一參數必須是變量(引用傳遞),非數組報 Warning
3. 指定鍵賦值 —— 關聯數組、覆蓋、稀疏索引
$arr = [];
$arr['name'] = 'John'; // 字符串鍵
$arr[10] = 'fixed'; // 指定數字索引(稀疏)
$arr['name'] = 'Jane'; // 覆蓋
// 最通用、語義最清晰、性能極佳(直接 HashTable 插入/更新)
4. array_unshift() —— 頭部插入、重建索引
$arr = ['b', 'c'];
array_unshift($arr, 'a'); // ['a','b','c'] 索引重建 0,1,2
array_unshift($arr, 'x', 'y'); // ['x','y','a','b','c']
// 所有現有數字鍵 +1,字符串鍵不變
// 大數組性能差:需重新分配內存、移動所有元素
5. array_merge() —— 頭部合併、保留字符串鍵
$arr = ['b' => 2, 'c' => 3];
$arr = array_merge(['a' => 1], $arr); // ['a'=>1, 'b'=>2, 'c'=>3]
// 數字鍵重建(0,1,2...),字符串鍵保留、後者覆蓋前者
// 常用於配置合併:$config = array_merge($defaults, $userConfig);
6. + 聯合運算符 —— 頭部合併、不覆蓋、保留鍵
$arr = ['b' => 2, 'c' => 3];
$arr = ['a' => 1] + $arr; // ['a'=>1, 'b'=>2, 'c'=>3]
$arr = ['a' => 99] + $arr; // ['a'=>1, 'b'=>2, 'c'=>3] 左側鍵優先,不覆蓋
// 數字鍵同理:[5=>'x'] + [5=>'y', 6=>'z'] => [5=>'x', 6=>'z']
// 極適合「默認值 + 用戶配置」模式
7. array_splice() —— 任意位置插入/替刪
$arr = ['a', 'b', 'd', 'e'];
array_splice($arr, 2, 0, ['c']); // ['a','b','c','d','e'] 索引 2 處插入
array_splice($arr, 1, 2, ['x','y']); // ['a','x','y','e'] 替換索引 1,2
// 返回被移除元素數組,原數組引用修改
// 內部需移動後續元素,大數組中間插入性能較差
8. 直接指定數字索引 —— 稀疏數組、固定位置
$arr = [];
$arr[100] = 'slot 100'; // 索引 100,前面 0-99 不存在
// count($arr) = 1,但 max index = 100
// 適用於位圖、固定槽位、ID 直接映射場景
關鍵陷阱與避坑指南
| 陷阱 | 錯誤代碼 | 正確代碼 | 原因 |
| array_push 添加關聯鍵 | array_push($arr, 'key' => 'val') | $arr['key'] = 'val' | array_push 忽略鍵,強制生成 0,1,2... |
| array_unshift 添加關聯鍵 | array_unshift($arr, 'k'=>'v') | $arr = ['k'=>'v'] + $arr | 同理,unshift 只接受值列表 |
| array_merge 數字鍵重建導致邏輯錯 | array_merge([5=>'a'], [6=>'b']) => [0=>'a', 1=>'b'] | [5=>'a'] + [6=>'b'] => [5=>'a', 6=>'b'] | merge 重建數字索引,+ 保留 |
| + 運算符不覆蓋導致默認值失效 | $config = $user + $defaults(用戶配置在左) | $config = $defaults + $user 或 array_merge($defaults, $user) | + 左側鍵優先,合併順序反了 |
| [] 語法誤用於關聯賦值 | $arr[] = ['key'=>'val'](產生嵌套數組) | $arr['key'] = 'val' | [] 只能追加值,不能指定鍵 |
性能基準(1000 萬次操作,PHP 8.2,大數組 10000 元素)
| 操作 | 耗時 | 備註 |
$arr[] = $v | 0.42s | 基準 |
array_push($arr, $v) | 0.58s | 函數調用開銷 |
$arr['k'] = $v | 0.45s | Hash 查找/插入 |
array_unshift($arr, $v) | 3.20s | 全量移動元素 |
array_merge([$k=>$v], $arr) | 2.80s | 創建新數組+複製 |
[$k=>$v] + $arr | 1.90s | 創建新數組+複製 |
array_splice($arr, 5000, 0, [$v]) | 1.60s | 中間插入移動後半段 |
現代最佳實踐建議
- 尾部追加:
$arr[] = $val(單個)、array_push($arr, ...$vals)(批量,PHP 7.3+)
- 關聯賦值/覆蓋:
$arr['key'] = $val
- 配置合併(用戶覆蓋默認):
$config = array_merge($defaults, $userConfig) 或 $config = $userConfig + $defaults(不覆蓋)
- 隊列/棧模擬:
array_push/array_pop(棧)、array_push/array_shift(隊列,但 array_shift 同樣 O(n)),大量操作請用 SplQueue/SplStack/SplDoublyLinkedList
- 大數組頻繁頭部/中間插入:改用
SplDoublyLinkedList(O(1) 插入刪除)或 Redis List(LPUSH/RPOP)
- 類型安全:PHP 8.1+ 使用
array 類型聲明、#[ArrayShape]、Rector 自動重構
總結
PHP 數組添加元素看似簡單,實則暗藏 索引重建、鍵覆蓋語義差異、性能數量級差距 等細節。牢記 「尾部用 [],關聯用指定鍵,合併用 merge/+,頭部/中間慎用或換數據結構」,即可寫出高性能、無 Bug 的數組操作代碼。