Reputation: 1559
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
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
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
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
Reputation: 66825
You could use the eval
function
if (eval('return '.$value['1'].$comparison.$value[$i]['2'].';')){
}
Upvotes: 0
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
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