php - 创建没有 eval 的动态 if 语句
问题描述
有一个系统可以抓取其他网站,用户可以获得有关抓取内容的信息。用户应该能够根据抓取的内容(假设它的整数)创建过滤器:如果内容小于/大于/等于特定用户所需的数字等,则跳过结果。所以 PHP 应该能够检查这些东西,换句话说:创建一个语句,检查抓取的结果是否有效,也可以选择过滤器。
例子:
在这里我们可以看到一个带有随机数的 Excel 表(就像一个抓取的网站):
用户通过某些过滤器创建和过滤排除数字(相同的示例 excel 过滤器):
系统获取过滤器并过滤结果:
现在我需要用 PHP 做同样的事情。我在考虑 eval 但它在我的 PHP 上被禁用。
PHP 示例:
// the content which was scraped
$scrapedResults = [1, 10, 11, 1216, 15, 55, 556, 123, 225, -15,];
// the user created filters
$filters = [
['filter' => ['more' => 0], 'operator' => null,],
['filter' => ['less' => 15], 'operator' => 'and'],
['filter' => ['equal' => 1216], 'operator' => 'or'],
];
// the filter checker
function isValid(string $action, int $ruleArgument, int $target): bool
{
switch ($action)
{
case 'more': return $ruleArgument > $target;
case 'less': return $ruleArgument < $target;
case 'equal': return $ruleArgument === $target;
default: throw new InvalidArgumentException('unknown action given');
}
}
$result = [];
foreach ($scrapedResults as $scrapedResult) {
foreach ($filters as $filter) {
// how to check with all of these filter clauses?
}
// by static this function shoud look like this:
// if($target > 0 && $target < 15 || $tager === 1216) { return true; } else { return false; }
// but how I should it created dynamically??
}
另一个 PHP 示例:
// the filter which user created:
$filters = [
['filter' => ['more' => 1], 'operator' => null,],
['filter' => ['less' => 15], 'operator' => 'and'],
['filter' => ['equal' => 1216], 'operator' => 'or'],
['filter' => ['equal' => 225], 'operator' => 'or'],
];
// the if clause which my code should generate:
// if($target > 1 && $target < 15 || $target === 1216 || $target === 225) {return true;} else {return false;}
这项任务有一个转折点。在 excel 过滤器中限制为 4 个附加过滤器。系统没有任何限制,所以我可以从 1 到 100000。
简而言之:我需要找到一种在没有 EVAL() 的情况下在 PHP 中创建 if 动态语句的方法
也欢迎任何有关此任务逻辑改进的建议!
解决方案
我已经使用闭包实现了这一点,有一组数组定义了用于过滤器类型和运算符的回调函数。
每次应用过滤器时,它首先检查过滤器是否正常,然后使用array_filter()
查找表中的相应回调来检查每个项目与过滤的值。一旦过滤了整个数字列表,它就会计算出如何将这些结果与以前的结果结合起来。回调再次知道这部分的逻辑......
// the content which was scraped
$scrapedResults = [1, 10, 11, 1216, 15, 55, 556, 123, 225, -15,];
// the user created filters
$filters = [
['filter' => ['more' => 0], 'operator' => null,],
['filter' => ['less' => 15], 'operator' => 'and'],
['filter' => ['equal' => 1216], 'operator' => 'or'],
];
// Implementation of the filters
$filterType = ['more' => function ($a, $b) { return $a > $b; },
'less' => function ($a, $b) { return $a < $b; },
'equal' => function ($a, $b) { return $a == $b; }];
// Implementation of the operators
$operators = ['and' => function ($old, $result ) {
return array_intersect($old, $result);
},
'or' => function ($old, $result ) {
return array_merge($old, $result);
}];
$output = [];
foreach ( $filters as $filter ) {
$currentType = array_keys($filter['filter'])[0];
if ( !isset($filterType[$currentType]) ) {
throw new InvalidArgumentException('unknown action given');
}
$filterValue = $filter['filter'][$currentType];
$callback = $filterType[$currentType];
$filterRes = array_filter($scrapedResults, function ($a)
use ($callback, $filterValue) {
return $callback($a, $filterValue);
});
if ( $filter['operator'] == null ) {
$output = $filterRes;
}
else if ( isset($operators[$filter['operator']]) ) {
$output = $operators[$filter['operator']]($output, $filterRes);
}
}
echo "output->";
print_r($output);
这输出...
output->Array
(
[0] => 1
[1] => 10
[2] => 11
[3] => 1216
)
推荐阅读
- python-3.x - 如何在列表中求平方根
- acumatica - 操作栏自定义项的可见性
- java - 当 net-snmp get 返回响应事件时,为什么 snmp 代理不接受 snmp4j get 上的请求
- azure-ad-b2c - 是否可以强制所有 Azure AD B2C MFA 都是电话而不是短信?
- excel - 将excel 1列转换为多个csv列
- android - Android build.gradle 中的许多符号“无法解析符号”导致构建失败
- jquery - Bootstrap 4.3.1 弹出框不显示弹出框内容内的表格
- git - git push 错误:pack-objects 死于信号 7
- c++ - 如何逐行读取,拆分字符串
- angularjs - AngularJS 应用程序中未识别的 ng-controller 问题