- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个网站运行在一个相当老的 PHP 5.6.38 安装上...现在我已经冒险将它移动到最新的 XAMPP 版本(使用 PHP 8.0.3)。
不出所料,需要进行一些更改,但我似乎无法整理的是与已弃用的“create_function”函数相关的更改。我用它来允许我通过一个或多个键名动态排序关联数组......例如:
usort($myarray, create_function('$a,$b', get_usort_function('field2 ASC, field5 ASC')));
现在,我读到我应该使用匿名函数,所以将代码更改为如下...
usort($myarray, function($a,$b) { get_usort_function('field2 ASC, field5 ASC'); } );
get_usort_function 用于创建比较所需的文本 - 因此对于上面的示例,它会返回类似于...
$field2=compare_ints($a['field2'], $b['field2']); if($field2==0){return compare_ints($a['field5'], $b['field5']);}else{return $field2;}
现在,在 PHP8 版本中,匿名函数不起作用 - 但如果我对 get_usort_function 返回的字符串进行硬编码,那么它就起作用了。我错过了什么吗?
一个简单的实际操作示例如下...
<?php
function compare_ints($val1, $val2)
{
return $val1 <=> $val2;
}
function dynamic_create_usort_function()
{
$str='return compare_ints($a[' . "'" . 'id' . "'" . '], $b[' . "'" . 'id' . "'" . ']);';
return $str;
}
$a1 = array( 'id' => 9, 'name' => 'Andy');
$a2 = array( 'id' => 5, 'name' => 'Bob');
$a = array($a1, $a2);
$s = dynamic_create_usort_function();
print "\n\n***$s***\n\n";
print_r($a);
usort($a, function($a,$b) { dynamic_create_usort_function(); } );
print_r($a);
usort($a, function($a,$b) { return compare_ints($a['id'], $b['id']); } );
print_r($a);
?>
上面的例子给出了...的输出
***return compare_ints($a['id'], $b['id']);***
Array
(
[0] => Array
(
[id] => 9
[name] => Andy
)
[1] => Array
(
[id] => 5
[name] => Bob
)
)
Array
(
[0] => Array
(
[id] => 9
[name] => Andy
)
[1] => Array
(
[id] => 5
[name] => Bob
)
)
Array
(
[0] => Array
(
[id] => 5
[name] => Bob
)
[1] => Array
(
[id] => 9
[name] => Andy
)
)
我真的很想解决这个问题,因为我的网站大量使用了这个 usort 函数!所以,很明显,需要最少的返工就是梦想......
提前致谢,达伦
最佳答案
create_function
接受两个字符串,即要创建的函数的参数和主体。在内部,它使用 eval
创建可调用的东西,这通常是不受欢迎的,因为它增加了攻击面。
根据您的描述,get_usort_function
函数返回一个字符串;如您所述,如果像这样调用:
get_usort_function('field2 ASC, field5 ASC')
它会返回如下内容:
$field2=compare_ints($a['field2'], $b['field2']); if($field2==0){return compare_ints($a['field5'], $b['field5']);}else{return $field2;}
您已经注意到,对传递给 usort
的可调用对象中的字符串进行硬编码是可行的,我想这类似于:
usort($myarray, function($a,$b) { $field2=compare_ints($a['field2'], $b['field2']); if($field2==0){return compare_ints($a['field5'], $b['field5']);}else{return $field2;} } );
但是根据上面对 get_usort_function
工作原理的描述,更准确的硬编码应该是:
usort($myarray, function($a,$b) { "$field2=compare_ints($a['field2'], $b['field2']); if($field2==0){return compare_ints($a['field5'], $b['field5']);}else{return $field2;}" } );
当像这样写出来时,很明显,将 usort
调用从 create_function
更改为使用可调用的,如您在上面指出的那样不会返回任何东西(所以 usort
将保留所有元素的现有顺序)。这可能是您对它的工作原理的理解不清楚的部分。
您可以执行如下操作(这可能类似于现有 get_usort_function
内部逻辑的简化版本):
<?php
function print_people($people) {
foreach($people as ['id' => $id, 'name' => $name]) {
print("{$id}: {$name}\n");
}
print("\n");
}
function get_usort_callable(...$fields) {
return function ($a, $b) use ($fields) {
foreach ($fields as $field) {
$result = $a[$field] <=> $b[$field];
if ($result != 0) { return $result; }
}
return 0;
};
}
$a1 = ['id' => 9, 'name' => 'Andy'];
$a2 = ['id' => 6, 'name' => 'Carol'];
$a3 = ['id' => 5, 'name' => 'Bob'];
$a = [$a1, $a2, $a3];
print_people($a);
usort($a, get_usort_callable('id', 'name'));
print_people($a);
usort($a, get_usort_callable('name', 'id'));
print_people($a);
给出以下输出:
9: Andy
6: Carol
5: Bob
5: Bob
6: Carol
9: Andy
9: Andy
5: Bob
6: Carol
这里的主要内容是在 get_usort_callable
返回的匿名函数上使用 use
关键字来使 $fields
可用。如果您想匹配现有 get_usort_function
的功能,您可以重写它以采用 string
,并将其拆分。
鉴于您将不得不从 create_function
转移到使用 PHP 8,您可以做的最少工作就是重写 get_usort_function
以返回一个可调用(与上面类似)并替换调用,如:
usort($myarray, create_function('$a,$b', get_usort_function(...)));
与:
usort($myarray, get_usort_function(...));
鉴于您可以访问 get_usort_function
的内部逻辑,它应该不会太困难,幸运的是这只是在一个地方。调用站点的重构也非常机械化,几乎可以用任何 IDE 进行查找和替换。
展望 future (并取决于您的偏好),您可能希望将 SQL ORDER BY
样式字符串替换为结构化数组,例如:
'field2 ASC, field5 ASC'
变成:
[
[
'field' => 'field2',
'direction' => 'asc'
],
[
'field' => 'field5',
'direction' => 'asc'
]
]
为了避免需要在 get_usort_function
中进行额外处理的空格等可能出现的问题。
create_function
与匿名函数从使用 create_function
到使用匿名函数时,您不再需要将函数的参数和主体作为字符串传递。例如,以下两个可调用对象是等效的:
create_function('$a,$b', 'return $a["id"] <=> $b["id"];')
function($a, $b) { return $a["id"] <=> $b["id"]; }
并且可以互换使用。
通过使用以下函数添加一级间接(正如您在问题中所拥有的):
function sort_by_function_body($field) {
return "return \$a[\"{$field}\"] <=> \$b[\"{$field}\"];";
}
function sort_by_callable($field) {
return function($a, $b) use ($field) { return $a[$field] <=> $b[$field]; };
}
这两个也是等价的:
create_function('$a,$b', sort_by_function_body('id'))
sort_by_callable('id')
主要的收获是 sort_by_callable
函数本身返回一个专门的匿名函数,它将对传入的字段进行排序,而不是包含执行相同逻辑的代码的字符串。
关于php - PHP 中的匿名函数内容不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66960268/
今天有小伙伴给我留言问到,try{...}catch(){...}是什么意思?它用来干什么? 简单的说 他们是用来捕获异常的 下面我们通过一个例子来详细讲解下
我正在努力提高网站的可访问性,但我不知道如何在页脚中标记社交媒体链接列表。这些链接指向我在 facecook、twitter 等上的帐户。我不想用 role="navigation" 标记这些链接,因
说现在是 6 点,我有一个 Timer 并在 10 点安排了一个 TimerTask。之后,System DateTime 被其他服务(例如 ntp)调整为 9 点钟。我仍然希望我的 TimerTas
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我就废话不多说了,大家还是直接看代码吧~ ? 1
Maven系列1 1.什么是Maven? Maven是一个项目管理工具,它包含了一个对象模型。一组标准集合,一个依赖管理系统。和用来运行定义在生命周期阶段中插件目标和逻辑。 核心功能 Mav
我是一名优秀的程序员,十分优秀!