3

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.

1
  • 1
    Firstly, Equal to is == not just one = Commented Aug 12, 2013 at 7:02

6 Answers 6

6

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.

Sign up to request clarification or add additional context in comments.

3 Comments

This is a much better approach than using eval.
@middaparka Though, create_function() behaves pretty much the same as eval() :)
Yes, it is. The only advantage that we can use direct call (no need to create temporary variable).
5

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'] . ';');

1 Comment

Of all the answers given, i think switch approach is most appropriate and basic. Thanks to all
1
$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

1 Comment

code in the form if ($x) { $y=true; } else { $y=false; } is highly redundant, simply write $y=(bool)$x;
1

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');
}

2 Comments

Probably the perfect solution, if you're running PHP 5.3 and above.
@middaparka Yeah, but 5.3 has been around for 4+ years :)
0
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');
}

Comments

0

You could use the eval function

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

}

2 Comments

The eval() language construct is very dangerous because it allows execution of arbitrary PHP code..See documentation php.net/manual/en/function.eval.php
knives are also dangerous yet you use them, don't you? If one uses it reasonably, it is a powerfull and interesting tool. Here, we have a $comparison taken from switch, if one also casts $value[$i] so it has to contain just numbers it is a 100% safe code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.