PHP 提供超過 100 個陣列函數,其中 array_column 與 array_multisort 是處理多維資料、報表排序的利器。本文透過實戰場景示範其進階用法。
array_column — 提取欄位、重建鍵值的雙重威力array_column(array $array, $column_key, $index_key = null): array
$column_key:要提取的欄位名(或索引)。$index_key(可選):以某欄位值作為新陣列的鍵。場景:從學生清單取出所有 ID,一次查詢其他表關聯資料(避免 N+1 查詢)。
$records = [
['id' => 2135, 'first_name' => 'John', 'last_name' => 'Doe'],
['id' => 3245, 'first_name' => 'Sally', 'last_name' => 'Smith'],
];
$ids = array_column($records, 'id');
// 結果:[2135, 3245]
// 直接用於 SQL IN 條件
$placeholders = implode(',', array_fill(0, count($ids), '?'));
$stmt = $pdo->prepare("SELECT * FROM profiles WHERE user_id IN ($placeholders)");
$stmt->execute($ids);
優勢:單行代碼替代 foreach 迴圈,可讀性高、效能優(C 級實作)。
場景:頻繁以 ID 隨機存取完整記錄。
$records = [
['id' => 2135, 'first_name' => 'John', 'last_name' => 'Doe'],
['id' => 3245, 'first_name' => 'Sally', 'last_name' => 'Smith'],
];
// 傳統 foreach 寫法
$byId = [];
foreach ($records as $rec) $byId[$rec['id']] = $rec;
// array_column 一行搞定
$byId = array_column($records, null, 'id');
/* 結果:
[
2135 => ['id' => 2135, 'first_name' => 'John', 'last_name' => 'Doe'],
3245 => ['id' => 3245, 'first_name' => 'Sally', 'last_name' => 'Smith'],
]
*/
注意:若 $index_key 有重複值,後者會覆蓋前者(同陣列鍵特性)。
array_multisort — 多鍵、多維、混合排序的瑞士刀array_multisort(
array &$array1, $sort_order1 = SORT_ASC, $sort_flags1 = SORT_REGULAR,
array &$array2, $sort_order2 = SORT_ASC, $sort_flags2 = SORT_REGULAR,
...,
array &$... // 最後一個參數為要排序的目標陣列(可多個)
): bool
$data = [
['price' => 67, 'sale_num' => 2],
['price' => 86, 'sale_num' => 1],
['price' => 85, 'sale_num' => 6],
['price' => 98, 'sale_num' => 2],
['price' => 86, 'sale_num' => 6],
['price' => 67, 'sale_num' => 7],
];
// 1. 先提取排序依據欄位
$price = array_column($data, 'price');
$sale_num = array_column($data, 'sale_num');
// 2. 多重排序:價格 DESC、銷量 ASC、最後帶上 $data 本身
array_multisort($price, SORT_DESC, $sale_num, SORT_ASC, $data);
/* 排序後 $data 變為:
price | sale_num
98 | 2
86 | 1 ← 價格相同(86),銷量 1 排前面
86 | 6
85 | 6
67 | 2 ← 價格相同(67),銷量 2 排前面
67 | 7
*/
關鍵點:
$price, $sale_num)必須與目標陣列($data)長度相同、順序對應。array_multisort 會原地修改所有傳入陣列(含依據陣列)。SORT_NUMERIC、SORT_STRING、SORT_NATURAL、SORT_FLAG_CASE 可控制比較行為。function multi_sort(array &$data, array $criteria): void {
// $criteria = [['field' => 'price', 'order' => SORT_DESC], ['field' => 'sale_num', 'order' => SORT_ASC]];
$args = [];
foreach ($criteria as $c) {
$args[] = array_column($data, $c['field']);
$args[] = $c['order'];
$args[] = $c['flags'] ?? SORT_REGULAR;
}
$args[] = &$data; // 目標陣列必須傳引用
array_multisort(...$args);
}
// 使用
multi_sort($products, [
['field' => 'price', 'order' => SORT_DESC],
['field' => 'rating', 'order' => SORT_DESC],
['field' => 'created_at', 'order' => SORT_ASC],
]);
| 操作 | foreach 迴圈 | array_column + array_multisort |
|---|---|---|
| 提取欄位 (10萬筆) | ~45 ms | ~8 ms (C 級) |
| 多鍵排序 (10萬筆) | ~120 ms (usort + 閉包) | ~35 ms |
| 記憶體 | 額外建立新陣列 | 原地排序,額外僅需依據陣列 |
array_multisort 會重置數值索引(0,1,2...),關聯鍵保留。若需保留原鍵,先 $keys = array_keys($data) 同步排序。SORT_REGULAR 下 null < 數字 < 字串,可用 SORT_NATURAL 或預處理填充預設值。SORT_STRING | SORT_FLAG_CASE。array_column 擅長「縱向切分」,array_multisort 擅長「橫向排序」,兩者結合能以極少代碼解決複雜報表排序需求,是 PHP 開發者必備工具箱。