- 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/
我正在为我的按钮使用 onClick 功能。我的按钮代码如下所示: Button 1 Button 2 我的 JS 函数如下所示: function fadeNext(selectedId, spee
首先,我想提一下,我理解每个人在不提供至少一些试验或错误的情况下提出问题的感受,但这纯粹是一种知识需求,话虽如此,我会去提前问。 我一直无法弄清楚如何将保存在 MySQL 表中的 600-1000 个
我想做的事情有点令人困惑,而且我英语不太好,所以我先把代码贴在这里,这样你就可以很容易地理解: 以下是表单内容: Testing for Stackoverflow Option1
我学习 SDL 二维编程已有一段时间了,现在我想创建一个结合使用 SDL 和 OpenGL 的程序。我是这样设置的: SDL_Init(SDL_INIT_VIDEO); window = SDL_Cr
我创建了 2 个 data-* 标签。数据类别和数据标签。单击 href 标签后,我想复制该数据类别和数据标签以形成输入。我的代码是:
我想用 CSS 换行。我正在使用内容。 td:before { content: "Test\A Test2"; } 它不工作。如何正确
这个问题已经有答案了: Java Class that implements Map and keeps insertion order? (8 个回答) 已关闭 6 年前。 我有一个 HashMap
我正在尝试使用 JMeter 执行端到端测试。测试涉及写入SFTP文件夹并从另一个SFTP文件夹读取写入操作生成的文件。 我能够使用 JMeter SSH SFTP 插件连接到 SFTP 文件夹,并能
您好,我有带有标准服务器端 Servlet 的 GWT 客户端。 我可以从 GWT 客户端上传文件并在服务器端读取其内容 我可以将其作为字符串发送回客户端 但是 我有 GWT FormPanel与操作
我在 Plone 4.3.9 中创建了一个自定义类型的灵巧性,称为 PersonalPage,必须只允许在特定文件夹中使用 成员文件夹/用户文件夹 . 在他的 FTI 中,默认情况下 False .
在新(更新)版本的应用程序中更改小部件布局的最佳做法是什么?当新版本提供更新、更好的小部件时,如何处理现有小部件? 最佳答案 我认为您必须向用户显示一个弹出窗口,说明“此版本中的新功能”并要求他们重新
在我的应用程序中,我使用支持 View 寻呼机和 PagerTabStrip。进入查看寻呼机我有一些 fragment ,进入其中一个我正在使用支持卡片 View 。运行应用程序后,所有卡片 View
我有以下布局文件。基本上我有谷歌地图,在左上角我有一个 TextView,我需要在其中每 15 秒保持一次计数器以刷新 map 。布局很好。
我使用如下结构: HashMap > > OverallMap 如果我这样做: OverallMap . clear ( ) clear() 丢弃的所有内容(HashMap 对象、Integer 对
我在数据库中有 1000 张图像。在页面加载时,我随机显示 60 张图片,当用户滚动时,我通过 AJAX 请求添加 20 张图片。 第一种方法 我所做的是将所有图像加载到一个容器中,然后隐藏所有图像并
我正在使用 woocommerce 创建一个网上商店。 我想在每个产品上添加一个包含产品信息的表格,例如颜色、交货时间等等。 但是当我添加这张表时。本产品消失后的所有内容。 我的表的代码: td {
This question already has an answer here: What does an empty value for the CSS property content do?
因此,我正在与我的 friend 一起为 Google Chrome 开发一个扩展程序,对于大多数功能(即日历、设置等),我们打开一个模式,这样我们就不必重定向到另一个页面。当您在内容之外单击时,我们
我将可变高度的 CSS 框设置为在更大的 div 中向左浮动。现在我想添加一个标题,其中文本在框的左侧垂直显示(旋转 90 度),如下面的链接所示(抱歉还不能发布图片)。 http://imagesh
相关页面位于 www.codykrauskopf.com/circus 如果您查看我页面的右侧,在半透明容器和浏览器窗口边缘之间有一个间隙。我看了看,出于某种原因,wrap、main、content
我是一名优秀的程序员,十分优秀!