函數簽名
function array_msort(array $ArrayData, string $KeyName1, string $SortOrder1 = 'SORT_ASC', string $SortType1 = 'SORT_REGULAR', ...)
- 支援多重排序:依序傳入「鍵名、排序順序、排序型別」三元組,可無限疊加。
- 內部使用
array_multisort() + eval() 動態構建排序邏輯。
- 回傳排序後的陣列 (保留原鍵名)。
完整函數代碼
function array_msort($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 => $info) {
foreach ($KeyNameList as $keyName) {
${$keyName}[$key] = $info[$keyName];
}
}
$evalStr = 'array_multisort(' . join(',', $SortRule) . ',$ArrayData);';
eval($evalStr);
return $ArrayData;
}
使用範例
$data = [
['id'=>1, 'name'=>'Apple', 'type'=>'fruit', 'price'=>10, 'stock'=>5],
['id'=>2, 'name'=>'Banana', 'type'=>'fruit', 'price'=>5, 'stock'=>20],
['id'=>3, 'name'=>'Carrot', 'type'=>'veg', 'price'=>8, 'stock'=>3],
['id'=>4, 'name'=>'Durian', 'type'=>'fruit', 'price'=>30, 'stock'=>1],
];
// 1. 單鍵升序
$sorted = array_msort($data, 'price', 'SORT_ASC');
// 結果: Banana(5), Carrot(8), Apple(10), Durian(30)
// 2. 多鍵:類型升序、價格降序、庫存升序
$sorted = array_msort($data,
'type', 'SORT_ASC', 'SORT_STRING',
'price', 'SORT_DESC', 'SORT_NUMERIC',
'stock', 'SORT_ASC', 'SORT_NUMERIC'
);
// 結果: veg類優先(Carrot),fruit類內部價格高到低(Durian, Apple, Banana),同價再按庫存
注意事項與現代替代方案
- eval 風險:若鍵名來自用戶輸入,必須嚴格白名單過濾,防止程式碼注入。
- PHP 5.5+ 推薦:使用
array_multisort 直接配合 array_column 更安全、效能更好:
$price = array_column($data, 'price');
$stock = array_column($data, 'stock');
array_multisort($price, SORT_ASC, $stock, SORT_ASC, $data);
PHP 8.0+:可用 usort 搭配箭頭函數寫法更直觀:
usort($data, fn($a, $b) => $a['price'] <=> $b['price'] ?: $a['stock'] <=> $b['stock']);