猿问

创建没有 eval 的动态 if 语句

有一个系统可以抓取其他站点,用户可以获得有关抓取内容的信息。用户应该能够根据抓取的内容创建过滤器(假设它是整数):如果内容小于/大于/等于特定用户所需的数字等,则跳过结果。因此 PHP 应该能够检查这些内容,换句话说:创建一个语句,检查抓取的结果是否有效,也选择了过滤器。

例子:

在这里我们可以看到一个带有随机数的 excel 表格(就像一个爬取的网站):

用户通过某些过滤器创建和过滤器排除数字(相同的示例 excel 过滤器): 

http://img4.mukewang.com/6184d83d00014e3d05690325.jpg

系统获取过滤器并过滤结果:

http://img2.mukewang.com/6184d84800015d0901960087.jpg

现在我需要用 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 动态语句


也欢迎任何有关此任务逻辑改进的建议!


慕的地8271018
浏览 124回答 1
1回答

德玛西亚99

我已经使用闭包实现了这一点,有一组数组定义了用于过滤器类型和运算符的回调函数。每次应用过滤器时,它首先检查过滤器是否正常,然后array_filter()与查找表中的相应回调一起使用,根据被过滤的值检查每个项目。一旦过滤了整个数字列表,它就会计算出如何将这些结果与之前的结果结合起来。再次回调知道这部分的逻辑......// the content which was scraped$scrapedResults = [1, 10, 11, 1216, 15, 55, 556, 123, 225, -15,];// the user created filters$filters = [&nbsp; &nbsp; ['filter' => ['more' => 0], 'operator' => null,],&nbsp; &nbsp; ['filter' => ['less' => 15], 'operator' => 'and'],&nbsp; &nbsp; ['filter' => ['equal' => 1216], 'operator' => 'or'],];// Implementation of the filters$filterType = ['more' => function ($a, $b) { return $a > $b; },&nbsp; &nbsp; 'less' => function ($a, $b) { return $a < $b; },&nbsp; &nbsp; 'equal' => function ($a, $b) { return $a == $b; }];// Implementation of the operators$operators = ['and' => function ($old, $result ) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return array_intersect($old, $result);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'or' => function ($old, $result ) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return array_merge($old, $result);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }];$output = [];foreach ( $filters as $filter ) {&nbsp; &nbsp; $currentType = array_keys($filter['filter'])[0];&nbsp; &nbsp; if ( !isset($filterType[$currentType]) ) {&nbsp; &nbsp; &nbsp; &nbsp; throw new InvalidArgumentException('unknown action given');&nbsp; &nbsp; }&nbsp; &nbsp; $filterValue = $filter['filter'][$currentType];&nbsp; &nbsp; $callback = $filterType[$currentType];&nbsp; &nbsp; $filterRes = array_filter($scrapedResults, function ($a)&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; use ($callback, $filterValue) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return $callback($a, $filterValue);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; if ( $filter['operator'] == null )&nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; $output = $filterRes;&nbsp; &nbsp; }&nbsp; &nbsp; else if ( isset($operators[$filter['operator']]) )&nbsp; &nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; $output = $operators[$filter['operator']]($output, $filterRes);&nbsp; &nbsp; }}echo "output->";print_r($output);这输出...output->Array(&nbsp; &nbsp; [0] => 1&nbsp; &nbsp; [1] => 10&nbsp; &nbsp; [2] => 11&nbsp; &nbsp; [3] => 1216)
随时随地看视频慕课网APP
我要回答