場景
需依二維陣列中某欄位(如 num、date)排序,保持鍵名關聯。
方法一:內建 array_multisort(推薦,效能最佳)
$arr = [
['date' => '2011-08-18', 'num' => 5],
['date' => '2011-08-20', 'num' => 3],
['date' => '2011-08-17', 'num' => 10],
];
// 1. 提取排序欄位建立索引陣列
$nums = array_column($arr, 'num');
// 2. 排序(索引陣列排序會同步調整主陣列)
array_multisort($nums, SORT_ASC, $arr);
// 結果:num 3, 5, 10
print_r($arr);
多欄位排序(先按 num 升序,再按 date 降序)
$nums = array_column($arr, 'num');
$dates = array_column($arr, 'date');
array_multisort($nums, SORT_ASC, SORT_NUMERIC, $dates, SORT_DESC, SORT_STRING, $arr);
array_multisort 參數速查
| 旗標 | 說明 |
| SORT_ASC | 升序(預設) |
| SORT_DESC | 降序 |
| SORT_REGULAR | 一般比較(預設) |
| SORT_NUMERIC | 數值比較 |
| SORT_STRING | 字串比較 |
| SORT_LOCALE_STRING | 依當前 locale 字串比較 |
| SORT_NATURAL | 自然排序(PHP 5.4+) |
| SORT_FLAG_CASE | 字串比較忽略大小寫(配合 SORT_STRING) |
方法二:通用函數 sysSortArray(支援動態多欄位、字串參數)
/**
* 多欄位排序二維陣列
* @param array $arrayData 待排序陣列
* @param string $keyName1 第一排序欄位
* @param string $sortOrder1 排序順序 SORT_ASC|SORT_DESC
* @param string $sortType1 排序類型 SORT_REGULAR|SORT_NUMERIC|SORT_STRING
* @param ... 可繼續傳入 keyName2, sortOrder2, sortType2...
* @return array 排序後陣列
*/
function sysSortArray($arrayData, $keyName1, $sortOrder1 = 'SORT_ASC', $sortType1 = 'SORT_REGULAR') {
if (!is_array($arrayData)) return $arrayData;
$argCount = func_num_args();
$keyNameList = [];
$sortRule = [];
for ($i = 1; $i < $argCount; $i++) {
$arg = func_get_arg($i);
if (!preg_match('/^SORT_/', $arg)) {
$keyNameList[] = $arg;
$sortRule[] = '$' . $arg;
} else {
$sortRule[] = $arg;
}
}
// 建立各欄位索引陣列
foreach ($arrayData as $key => $row) {
foreach ($keyNameList as $keyName) {
${$keyName}[$key] = $row[$keyName];
}
}
// 動態構建並執行 array_multisort
$evalStr = 'array_multisort(' . implode(',', $sortRule) . ', $arrayData);';
eval($evalStr);
return $arrayData;
}
// 使用範例
$result = sysSortArray($arr, 'num', 'SORT_ASC', 'SORT_NUMERIC', 'date', 'SORT_DESC', 'SORT_STRING');
方法三:usort 自訂比較函數(彈性最高,效能較差)
usort($arr, function($a, $b) {
// 先比 num
if ($a['num'] !== $b['num']) return $a['num'] <=> $b['num'];
// num 相同比 date 降序
return strcmp($b['date'], $a['date']);
});
效能比較(10,000 筆資料)
| 方法 | 耗時(ms) | 備註 |
| array_multisort + array_column | ~5 | C 級函數,最快 |
| sysSortArray (eval) | ~12 | eval 開銷,動態參數方便 |
| usort + spaceship operator | ~45 | PHP 回調開銷大 |
最佳實踐建議
- 固定欄位排序:直接用
array_column + array_multisort。
- 動態欄位(如使用者點擊表頭排序):封裝
sysSortArray 或自行組裝 array_multisort 參數,避免 eval。
- 複雜邏輯(多層條件、自訂比較):使用
usort / uasort(保持鍵名)。
- 大資料集(>10萬筆):在資料庫層用
ORDER BY 完成,勿在 PHP 排序。