I have a PHP array like so:
$booleans = array(true, '||', false, '&&', true, '||', false);
Now I would now like to convert this array to a condition, e.g.:
if(true || false && true || false){
// Do something
}
else{
// Do something else
}
Preferably, for security reasons, I want to avoid using eval
.
Is this possible? If so, what is the most efficient way to do it?
CodePudding user response:
This is not a finite solution for all operations and precedence, but a direction on how you may resolve it. You can refer to Shunting yard algorithm .
$validateExpression = function (array $expression): bool {
$allowedOperators = ['&&', '||'];
$values = [];
$operators = [];
foreach ($expression as $expr) {
if (is_bool($expr)) {
$values[] = $expr;
continue;
}
if (in_array($expr, $allowedOperators)) {
$operators[] = $expr;
continue;
}
throw new \InvalidArgumentException('Invalid expression');
}
while($operators) {
$a = array_shift($values);
$b = array_shift($operators);
$c = array_shift($values);
array_unshift($values, match($b) {
'&&' => $a && $c,
'||' => $a || $c,
});
}
return reset($values);
};
var_dump($validateExpression([true, '||', false, '&&', true, '||', false]));
var_dump(true || false && true || false);
Output
bool(true)
bool(true)
CodePudding user response:
Make sure that array is well-formatted and you can use this code:
<?php
function parseArray(array $booleans): bool
{
$result = false;
for ($i = 0; $i < count($booleans); $i = 2) {
if ($i 1 === count($booleans) || $booleans[$i 1] === '||') {
$result = $result || $booleans[$i];
continue;
}
$andResult = $booleans[$i];
while ($booleans[$i 1] === '&&') {
$i = 2;
$andResult = $andResult && $booleans[$i];
if ($i 1 === count($booleans)) {
break;
}
}
$result = $result || $andResult;
}
return $result;
}
var_dump(parseArray([false]));
var_dump(parseArray([true]));
var_dump(parseArray([true, '&&', false]));
var_dump(parseArray([true, '&&', true]));
var_dump(parseArray([true, '||', false]));
var_dump(parseArray([false, '||', false]));
var_dump(parseArray([false, '||', false, '&&', true, '||', false]));
var_dump(parseArray([true, '||', false, '&&', true, '||', false]));
First of all collapse all &&
because they have higher priority, then calculate all ||
CodePudding user response:
Seems a bit weird to me why you'd want to do that. But for complex repetitive validations you may use functions.
Like so:
function validate($params) {
return true || false && true || false; // Maybe you'd want to use $params in there at some point?
}
Then you can use it in an if statement
if(validate($myParam)){
// Do something
}
else{
// Do something else
}
I still don't understand WHY you'd want what you have shown in your question but I think you may be able to accomplish what you want with a similar type of function(s).