usort() 用于按值排序且不保留键名,uasort() 保留原键名;比较函数必须返回 -1、0、1,不可用布尔表达式;字符串用 strcmp(),浮点数需 round() 后比较。

排序结果不对,先看 sort() 和 usort() 的根本区别
PHP 里最常踩的坑是拿 sort() 去排关联数组——它会重置键名,把 ['name' => 'a', 'age' => 25] 变成索引数组,键全丢光。真要按字段排序,必须用 usort() 或 uasort()。
关键判断点:
- 要保留原键(比如数组下标是用户 ID),用 uasort()
- 只关心值顺序、不care键,用 usort()
- 想按字符串自然顺序排(比如 "10" 在 "2" 后面),得在回调里加 strcmp() 或 strnatcmp()
回调函数里 return 值写错,排序就完全乱序
usort() 的比较函数必须严格返回整数:-1(前小后大)、0(相等)、1(前大后小)。写成 return $a > $b 这种布尔值,PHP 会转成 1 或 0,漏掉 -1,排序逻辑直接崩。
正确写法示例(按数字升序):
usort($arr, function($a, $b) {
return $a['score'] <=> $b['score']; // PHP 7+ 船箭操作符,安全又简洁
});
- 老版本 PHP 用
return ($a['score'] $b['score']) ? 1 : 0); - 字符串排序别用
==或===判断,要用strcmp($a['name'], $b['name']) - 浮点数慎用
,可能有精度误差,建议先round()再比
调试时直接 var_dump() 排序前后的数组太粗糙
只看首尾几个元素,根本发现不了中间某几项顺序异常。真正有效的做法是加一层「校验输出」:
在排序后插入这段代码:
foreach ($arr as $i => $item) {
$prev = $i > 0 ? $arr[$i - 1] : null;
if ($prev !== null && $item['score'] < $prev['score']) {
echo "⚠️ 错位:索引 {$i} 的 score({$item['score']}) 小于前一项({$prev['score']})\n";
}
}
- 这个检查能立刻暴露是否真排序失败,还是数据本身含空值或非数字
- 如果报错,立刻查那两个元素的原始值——常见原因是某个
'score'是null或字符串"N/A" - 别依赖浏览器直接看
var_dump,用 CLI 运行脚本,输出更干净
多维排序需求别硬套单层 usort()
想先按 status 分组(active 在前),再按 created_at 倒序,一个回调里硬写嵌套判断容易出错。更稳的方式是用 array_multisort() 拆解维度:
立即学习“PHP免费学习笔记(深入)”;
$statuses = array_column($arr, 'status'); $times = array_column($arr, 'created_at'); array_multisort($statuses, SORT_DESC, $times, SORT_DESC, $arr);
-
array_multisort()对 NULL 或非标量值容忍度低,执行前先array_filter($arr, function($x) { return isset($x['status'], $x['created_at']); }) - 它会修改原数组,不需要赋值回
$arr = ... - 如果字段是对象属性,得先用
array_map()提取出来,不能直接传$arr['prop']
实际排错时,90% 的问题出在数据类型不一致或回调返回值非法。花 30 秒加个校验循环,比反复改回调逻辑快得多。



















