usort回调函数必须返回整数,否则排序不可靠;应显式返回-1、0或1,避免布尔值等非整数导致类型转换错误,多条件排序需用if-else确保每条路径返回明确整数。

usort 回调函数返回非整数(比如布尔值、浮点数、字符串或 null)会导致排序结果不可靠甚至完全错乱。
非整数返回引发的核心问题
PHP 内部会把回调的返回值强制转为整数。例如:
-
return true / false → 转成
1或0,永远无法表达“小于”关系(缺 -1),导致所有比较都被视为“≥”,排序退化为随机或保持原序; -
return 0.99 / 0.1 → 都转成
0,系统认为两个元素“相等”,破坏排序稳定性与逻辑顺序; -
return "1" 或 null → 类型转换后可能得
0或意外值,引发未定义行为,不同 PHP 版本表现可能不一致。
确保返回整数的正确写法
比较函数必须显式返回 -1、0 或 1(或任意负/零/正整数),不能依赖隐式转换。常见安全模式:
-
数字比较:用减法,如
return $a['score'] - $b['score']; -
字符串比较:用
strcmp()或strcasecmp(),如return strcmp($a['name'], $b['name']); - 多条件判断:用 if-else 显式分支,每条路径都返回明确整数:
usort($items, function($a, $b) {<br> if ($a['type'] !== $b['type']) {<br> return $a['type'] === 'urgent' ? -1 : 1;<br> }<br> return $b['priority'] - $a['priority']; // 优先级降序<br>});
实现稳定排序的关键要点
PHP 的 usort 本身不保证稳定性(即相等元素的原始相对位置可能改变),但可通过以下方式模拟稳定行为:
- 在原始数组中预添加唯一索引字段(如
'_index' => $key),并在比较逻辑末尾加入该字段作为最终判据; - 当主排序条件相等时,用索引升序确保原有顺序不被打破;
- 避免使用
==或===直接返回布尔值,始终走整数分支。
调试建议
开发时可在回调中临时加日志:error_log("cmp: {$a['id']} vs {$b['id']} → {$result}");,确认每次返回值确为 -1/0/1;上线前用 assert(is_int($result)) 辅助验证(需开启 assert 检查)。

















