Оцените строку как условие PHP - PullRequest
0 голосов
/ 13 сентября 2018

У меня есть пользовательский модуль правил проверки, который, по сути, позволяет пользователям настраивать проверку CSV. Моя проблема, я получаю это в этот массив:

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

Я провел небольшое исследование и обнаружил функцию eval().

ссылки: Как использовать строку в условии IF в PHP

Однако я действительно не хочу использовать eval() из-за проблем с безопасностью (ref: Когда в php eval evil? )

Хотя в нем не говорится, что eval - это зло, я все же предпочел бы, если бы был альтернативный метод.

Я слишком осторожен с использованием eval() - возможно, мне следует сбежать и использовать eval() или есть лучший способ?

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

Просто ухожу от @deceze ответа и предложения использовать компонент Symfony ExpressionLanguage.

Я установил его в свой проект через Composer и подумал, что для всех, кто наткнулся на пост, было бы полезно увидеть, как оно работает (и в связи с моим вопросом):

<code># 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 '
'; # foreach тестовый ряд, проверка на соответствие условию foreach ($ test as $ key => $ item) { echo '
';
    var_dump($key. ': ' .$expressionLanguage->evaluate(
        $item['evaluate'],
        $item['pass']
    ));
    echo '
'; echo '+ ----------------------------------------------- ----------------------------- + '; }

Это теперь оценивает мои собственные строки php-запроса через компонент ExpressionLanguage Symfony. Спасибо @ deceze

рефов:

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

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

0 голосов
/ 13 сентября 2018

Что ж, выполнение произвольных строк в виде кода имеет оговорку, что вы выполняете произвольный код , в зависимости от того, как вы это делаете. Нет лучшей альтернативы eval, которая позволила бы вам выполнять код PHP без… выполнения кода PHP.

Разумный способ пойти сюда - определить DSL , который дает вашим пользователям возможность писать определенные ограниченные выражения , которые не являются PHP-кодом , которые вы будете анализировать и оценивать с помощью определенные ограниченные возможности.

Хорошая библиотека, которая делает это Компонент Symfony ExpressionLanguage . Кроме того, вы попадаете в область синтаксических анализаторов языка.

...