我很高兴能在PHP 7.4中让它工作,但现在它在PHP 8.1.14中又坏了。
任务是按标题对一个页面数组进行排序,但要以一种简化的方式。排序时,前导非字母将被忽略。
这是一个示例代码:
$pages = [
'a' => ['title' => 'A'],
'c' => ['title' => 'C'],
'b' => ['title' => 'B'],
'n' => ['title' => '.N'],
];
array_multisort(
$pages,
SORT_ASC,
SORT_STRING,
array_map(fn($page) =>
preg_replace('_^[^0-9a-z]*_', '', strtolower($page['title'])
), $pages)
);
echo implode(', ', array_map(fn($page) => $page['title'], $pages));
它在PHP 7.4中排序为以下输出,错误日志中没有任何内容:A, B, C, .N
在PHP 8.1中,我得到了这个错误:
ErrorException: Array to string conversion in ...\index.php:30
Stack trace:
#0 [internal function]: {closure}()
#1 ...\index.php(30): array_multisort()
我不明白问题出在哪里。PHP 8在这里做了什么改变,我能做些什么来再次修复代码?
更新/澄清:
在PHP 7.4中,有一个“Notice”,文本为“Array to string conversion”。在PHP 8.1中,这已更改为“Warning”。我将警告视为错误,因此在我的情况下它失败了。
这并没有改变PHP认为我的代码是错误的,我不知道为什么。
5条答案
按热度按时间brjng4g31#
你看起来把数组倒过来了。第一个数组是实际排序的,第二个数组应用了相同的转换。
ryoqjall2#
问题不在于PHP代码,而在于您使用
array_multisort()
的方式。第三个参数(
array_sort_flags
)告诉array_multisort()
如何比较第一个参数(要排序的数组)的项。值SORT_STRING
表示 “将项作为字符串进行比较” 但$pages
的项不是字符串而是数组。当数组在字符串上下文中使用时,PHP会抛出你看到的警告。在PHP 8之前,它曾经是一个通知,在PHP 8中它已经(正确地)升级为警告。在未来的PHP版本中,它甚至可以更改为错误。
不要隐藏通知,很多时候它们会显示逻辑错误。PHP过去非常宽容,并将此类错误报告为通知;自从PHP 8以来,其中许多都被提升为警告。修复代码,使其不会产生错误,警告甚至通知。
有多种方法可以修复此代码,但正确的方法取决于您的预期结果。如果
array_map()
转换后属性title
的值是唯一的,则颠倒数组的顺序可以解决这个问题:它仍然比较
$pages
数组中的项,但仅当它在第一个数组中遇到重复值时。另一种更易于阅读和理解但性能稍差的解决方案是使用
uasort()
对$pages
进行排序,使用当前传递给array_map()
的回调来比较元素检查online。
如果
$pages
很大,那么每次比较都调用preg_replace()
和strtolower()
会浪费时间。更好的解决方案是只计算一次排序键,并将它们保存在一个单独的数组中,让比较函数从这个数组中获取它们:检查online。
rsaldnfx3#
作为替代,您可以使用
uasort
。qij5mzcb4#
如果在排序之前隔离标题列数据,就可以避免代码中出现太多的混乱。
我建议只在匹配的字符串有长度的情况下进行替换。此外,只要还包含
SORT_STRING
,就可以使用SORT_FLAG_CASE
进行不区分大小写的排序。代码:(Demo)
请记住,
array_multisort()
实际上会做名字所暗示的事情。前三个参数中描述的排序规则将是第一轮排序。如果在第一轮之后有任何平局,第四个参数(未更改的值数组)将用于尝试打破平局。Demozfciruhq5#
PHP 7.4和8.1应该没有什么区别,可能只是之前的警告被抑制了(服务器设置,PHP配置),问题是他们错误地使用了函数。