为了账号安全,请及时绑定邮箱和手机立即绑定

创建没有 eval 的动态 if 语句

创建没有 eval 的动态 if 语句

PHP
慕的地8271018 2021-11-05 15:07:09
有一个系统可以抓取其他站点,用户可以获得有关抓取内容的信息。用户应该能够根据抓取的内容创建过滤器(假设它是整数):如果内容小于/大于/等于特定用户所需的数字等,则跳过结果。因此 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 checkerfunction 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 动态语句也欢迎任何有关此任务逻辑改进的建议!
查看完整描述

1 回答

?
德玛西亚99

TA贡献1770条经验 获得超3个赞

我已经使用闭包实现了这一点,有一组数组定义了用于过滤器类型和运算符的回调函数。


每次应用过滤器时,它首先检查过滤器是否正常,然后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

)


查看完整回答
反对 回复 2021-11-05
  • 1 回答
  • 0 关注
  • 123 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信