将字符串评估为条件PHP

问题描述 投票:2回答:2

我有一个自定义验证规则模块,基本上允许用户设置CSV验证。我的问题是我得到了这个数组:

Array(
    [field_name] => 'is_int(324230435)',
    [some_other_field] => 'strlen("some str") > 25'
)

我做了一些研究,并发现了eval()功能。

refs:How to use string in IF condition in PHP

但是,由于安全问题,我真的不想使用eval()(参考:When is eval evil in php?

虽然它并没有严格地说eval是邪恶的,但我还是更愿意,如果有另一种方法。

我对eval()的使用过于谨慎 - 也许我应该逃避并使用eval()或者有更好的方法吗?

php eval
2个回答
2
投票

好吧,执行任意字符串作为代码有一个警告,即你正在执行任意代码,无论你采用哪种方式。没有更好的替代eval可以让你执行PHP代码而无需执行PHP代码。

这里有一个明智的方法是定义一个DSL,它为用户提供了一种编写某些有限表达式的方法,这些表达式不是PHP代码,您将使用特定的有限功能对其进行解析和评估。

一个很好的图书馆就是Symfony's ExpressionLanguage component。除此之外,你将进入语言解析器领域。


0
投票

离开@deceze回答和建议使用Symfony的ExpressionLanguage组件。

我通过Composer将它安装到我的项目中,并认为任何在帖子中绊倒的人都可能看到它有用(并且与我的问题相关):

# build array for testing rows against rules
$test = [];

# foreach csv row
foreach ($csv as $keey => $row)
{
    # 10000s of rows, just for simplicity - break after 3
    if ($keey == 0) {continue;}
    if ($keey >= 3) {continue;}

    # get array keys for 
    $keys = array_keys($row);

    foreach ($keys as $key)
    {
        # if row key is in the $conditions array, add to $test array for testing
        if (in_array($key, array_map('strtolower', array_keys($conditions)))) {
            $conditionType = array_keys($conditions[$key]);
            $conditionType = $conditionType[0];

            if ($conditionType === 'condition_suffix') {
                $brokenCondition = explode(' ', $conditions[$key][$conditionType]);

                # build array to pass into ->evaluate()
                $test[$key]['evaluate'] = 'field '. $brokenCondition[0] .' required'; # expression to actually test
                $test[$key]['pass'] = [ # works like pdo, pass in the names and give them a value
                    'field' => strlen($row[$key]),
                    'required' => $brokenCondition[1]
                ];
            } else {
                $test[$key]['evaluate'] = 'field == required';
                $test[$key]['pass'] = [
                    'field' => is_numeric($row[$key]),
                    'required' => true
                ];
            }
        }
    }
}

echo '#----------------------------------------------------------------------------#';

# show test arr for reference
echo '<pre>';
print_r($test);
echo '</pre>';

# foreach test row, check against the condition
foreach ($test as $key => $item)
{
    echo '<pre>';
    var_dump($key. ': ' .$expressionLanguage->evaluate(
        $item['evaluate'],
        $item['pass']
    ));
    echo '</pre>';

    echo '+----------------------------------------------------------------------------+';
}

现在,这将通过ExpressionLanguage Symfony组件评估我自定义创建的php查询字符串。谢谢@deceze

裁判:

https://symfony.com/doc/current/components/expression_language/syntax.html

https://symfony.com/doc/current/components/expression_language.html

© www.soinside.com 2019 - 2024. All rights reserved.