Reputation: 6560
I have a custom validation rule module that essentially allows users to set up CSV validation. My problem is I get it to this array:
Array(
[field_name] => 'is_int(324230435)',
[some_other_field] => 'strlen("some str") > 25'
)
I did some research and came across the eval()
function.
refs: How to use string in IF condition in PHP
However, I really don't want to use eval()
due to the security issues (ref: When is eval evil in php?)
Although it doesn't strictly say eval is evil, I still would prefer if there was an alternative method.
Am I being over-cautious about the usage of eval()
- perhaps I should escape and use eval()
or is there a better way?
Upvotes: 2
Views: 2079
Reputation: 6560
Just going off of @deceze answer and suggestion to use Symfony's ExpressionLanguage Component.
I installed it to my project via Composer and thought for anyone stumbling across the post it might be helpful to see it working (and in relation to my question):
# 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 '+----------------------------------------------------------------------------+';
}
This now evaluates my custom created php query strings via the ExpressionLanguage Symfony component. Thanks @deceze
refs:
https://symfony.com/doc/current/components/expression_language/syntax.html
https://symfony.com/doc/current/components/expression_language.html
Upvotes: 0
Reputation: 522005
Well, executing arbitrary strings as code has the caveat that you're executing arbitrary code whichever way you do it. There's no better alternative to eval
that would let you execute PHP code without… executing PHP code.
The sane way to go here is to define a DSL which gives your users a way to write certain limited expressions which are not PHP code, which you will parse and evaluate with specific limited capabilities.
A good library which does that is Symfony's ExpressionLanguage component. Beyond that you'd go into the domain of language parsers.
Upvotes: 3