Talha Malik
Talha Malik

Reputation: 1559

Using IF condtion with comparison operator stored in variable

I have set of rules which involves comparison operators. I want to do some task based on the value of comparison operator stored in the rule. I am doing it in the following way but it is not working. Check the following code

if($benRules[$i]['amountCriteria']=='Greater than')
    $comparison='>';
if($benRules[$i]['amountCriteria']=='Equal to')
    $comparison='==';
if($benRules[$i]['amountCriteria']=='Less than')
    $comparison='<';

if($value['1'].$comparison.$value[$i]['2']){
    debug('Condtion checked');
}

problem is it always checks the condition to be true. it takes whole parameter inside IF condition to be string so as long as that string is not empty is executes the code inside the parenthesis. Please help me here.

Upvotes: 3

Views: 2433

Answers (6)

Ja͢ck
Ja͢ck

Reputation: 173602

This kind of construct is not possible without some kind of magic, either create_function() or eval().

However, you can also use a closure to achieve what you want; return a comparison function based on the operator that you want to use. You could consider this a cheap version of the Strategy pattern:

function getComparisonFunction($operator)
{
    // comparison function is returned
    return function($a, $b) use ($operator) {
        if ($operator == 'Greater than') {
            return $a > $b;
        } elseif ($operator == 'Equal to') {
            return $a == $b;
        } else { // Less than
            return $a < $b;
        }
    }
}
// get comparison function
$fn = getComparisonFunction($benRules[$i]['amountCriteria']);

// use comparison function
if ($fn($value['1'], $value[$i]['2'])) {
    debug('Condtion checked');
}

Upvotes: 1

m1k1o
m1k1o

Reputation: 2364

$str = "$result = (bool)($value['1'] $comparison $value[$i]['2']);";
eval($str);
if($result){
  //true
}

You can use eval(), but this also works:

            if($benRules[$i]['amountCriteria']=='Greater than'){
              $comparison = (bool)($value['1'] > $value[$i]['2']);
            }

            if($benRules[$i]['amountCriteria']=='Equal to'){
              $comparison = (bool)($value['1'] == $value[$i]['2']);
            }

            if($benRules[$i]['amountCriteria']=='Less than'){
              $comparison = (bool)($value['1'] < $value[$i]['2']);
            }

            if($comparison){
                debug('Condtion checked');
            }

EDIT

This looks better

Upvotes: 1

John Parker
John Parker

Reputation: 54445

It always evaluates to true as you're simply evaluating the existence of a string (you can't construct logical statements in this manner in PHP).

To achieve what you're attempting, you'd need to either use a switch statement (where you simply have a one to one match for each potential comparison operator) like so...

switch ($comparison) {
    case '<': { if($value['1'] < $value[$i]['2']) { ... } break; }
    case '==': { if($value['1'] == $value[$i]['2']) { ... } break; }
    case '>': { if($value['1'] > $value[$i]['2']) { ... } break; }
}

...or use eval to parse the logic. If might seem like a no-brainer to use the eval approach, but as the PHP manual admits:

The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.

As such, if you don't understand the risks involved, please stick with the switch approach. That said, a basic solution using eval would resemble the following:

eval('return ' . $value['1'] . $comparison . $value[$i]['2'] . ';');

Upvotes: 5

lejlot
lejlot

Reputation: 66825

You could use the eval function

if (eval('return '.$value['1'].$comparison.$value[$i]['2'].';')){

}

Upvotes: 0

mccakici
mccakici

Reputation: 550

if($benRules[$i]['amountCriteria']=='Greater than')
    $comparison='>';
if($benRules[$i]['amountCriteria']=='Equal to')
    $comparison='==';
if($benRules[$i]['amountCriteria']=='Less than')
    $comparison='<';

eval('$bool = $value[\'1\']'.$comparison.'$value[$i][\'2\'];');

if($bool){
    debug('Condtion checked');
}

Upvotes: 0

Alma Do
Alma Do

Reputation: 37365

Your problem is that you're trying to use string as a code without evaluating it. You can use create_function() like this:

$sCondition = '<';
$mData0     = 4;
$mData1     = 5.5;
$fnCallback=create_function('$x, $y', 'return $x'.$sCondition.'$y;');
var_dump($fnCallback($mData0, $mData1)); // true

Alternatively, there is an eval() function, but it seems direct returning will be more useful in your case.

Upvotes: 6

Related Questions