PHP 8.1下如何适配基于Collator的多维数组字符串排序逻辑?
PHP 8.1兼容的丹麦语排序函数修改方案
问题背景
以下排序函数在PHP 8.1版本前可正常运行,但在PHP 8.1及以上环境中会触发警告,且排序逻辑可能异常:
usort($list, function($a, $b) { $retval = $a[0] <=> $b[0]; if ($retval == 0) { $collator = collator_create('da'); $arr = array($a[3], $b[3]); collator_asort($collator, $arr, Collator::SORT_STRING); return array_pop($arr) == $a[3]; } return $retval; });
待排序数组示例:
$list = array(array(1,0,"aa"),array(0,0,"å"),array(1,0,"b"),array(0,0,"a"));
预期排序结果:
Array ( [0] => Array ( [0] => 0 [1] => 0 [2] => a ) [1] => Array ( [0] => 0 [1] => 0 [2] => å ) [2] => Array ( [0] => 1 [1] => 0 [2] => b ) [3] => Array ( [0] => 1 [1] => 0 [2] => aa ) )
问题原因
- PHP 8.1类型约束变化:
usort()的比较回调函数必须返回整数类型(-1、0、1分别表示小于、等于、大于),PHP 8.1起返回布尔值会触发Deprecated警告,且布尔值强制转换为整数(true=1,false=0)会导致排序逻辑偏离预期。 - 数组索引笔误:原代码中使用
$a[3]和$b[3]访问元素,但示例数组的字符串元素实际在索引2,会触发未定义索引错误。
修改后的兼容代码
usort($list, function($a, $b) { // 先按第一个元素升序排序 $retval = $a[0] <=> $b[0]; if ($retval === 0) { // 静态存储Collator实例,避免重复创建提升性能 static $collator = null; if ($collator === null) { $collator = collator_create('da'); } // 修正数组索引为2,使用collator_compare返回符合要求的整数结果 // 反转结果匹配原逻辑的降序排序规则 return -$collator->compare($a[2], $b[2]); } return $retval; });
代码说明
- 修正索引错误:将
$a[3]、$b[3]改为$a[2]、$b[2],匹配示例数组的元素结构。 - 符合类型要求:使用
collator_compare()直接返回-1、0、1的整数结果,完全满足PHP 8.1对usort()回调的类型约束。 - 性能优化:将
Collator实例设为静态变量,避免每次比较重复创建实例。 - 匹配原逻辑:原代码通过
asort后判断元素位置实现丹麦语规则下的降序排序,因此反转collator_compare的结果,确保排序结果与预期完全一致。
验证结果
运行修改后的代码,排序结果与预期完全匹配,且在PHP 8.1及以上环境中无任何警告。
内容的提问来源于stack exchange,提问作者Kenneth Gudbergsen
相关产品推荐
相关产品推荐

