Home > Blockchain >  PHP - Best way to parse array of conditions
PHP - Best way to parse array of conditions

Time:11-08

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).

  • Related