PHP 8中usort排序结果异常:是Bug还是代码需调整?
PHP8中usort排序异常问题解析
问题场景
我编写了一段代码,意图将数组中的'BMW'排序至首位:
$cars=['Toyota','Volvo','BMW']; usort($cars,function($v){return $v <=> 'BMW';}); var_export($cars);
不同版本结果差异
- PHP7及更低版本结果符合预期:
array ( 0 => 'BMW', 1 => 'Volvo', 2 => 'Toyota', )
- PHP8中的结果不符合预期:
array (0 => 'Volvo', 1 => 'BMW', 2 => 'Toyota',)
排查过程
经确认,问题并非出自太空船运算符(<=>),该运算符表现正常:
var_dump( 'Volvo' <=> 'BMW', 'BMW' <=> 'Volvo', 'BMW' <=> 'Toyota', 'Toyota' <=> 'BMW', 'BMW' <=> 'BMW' );
问题本质及解决方案
这不是PHP8的Bug,而是PHP8对usort回调函数的参数要求变得严格了。
usort的回调函数必须接收两个参数(待比较的两个元素$a和$b),通过返回值定义二者的排序关系:
- 返回负数:
$a排在$b前面 - 返回正数:
$a排在$b后面 - 返回0:二者顺序不变
在PHP7及更早版本中,即使回调只定义了一个参数,PHP会自动补全第二个参数为null,勉强让排序逻辑“工作”;但PHP8开始严格执行回调参数的合规性,单参数的回调会导致排序算法无法正确比较元素对,最终出现不符合预期的排序结果。
修正后的代码
要实现将'BMW'排到首位的需求,正确的回调写法应该是:
$cars=['Toyota','Volvo','BMW']; usort($cars, function($a, $b) { // 优先将BMW放到前面 if ($a === 'BMW') return -1; if ($b === 'BMW') return 1; // 其他元素按常规字符串排序 return $a <=> $b; }); var_export($cars);
或者用更简洁的箭头函数写法(PHP7.4+支持):
$cars=['Toyota','Volvo','BMW']; usort($cars, fn($a, $b) => ($a === 'BMW' ? -1 : ($b === 'BMW' ? 1 : $a <=> $b))); var_export($cars);
运行修正后的代码,在PHP7和PHP8中都能得到预期结果:
array ( 0 => 'BMW', 1 => 'Toyota', 2 => 'Volvo', )
内容的提问来源于stack exchange,提问作者jspit
相关产品推荐
相关产品推荐

