BenTheDesigner
BenTheDesigner

Reputation: 1984

Dynamic Comparison Operators in PHP

Is it possible, in any way, to pass comparison operators as variables to a function? I am looking at producing some convenience functions, for example (and I know this won't work):

function isAnd($var, $value, $operator = '==')
{
    if(isset($var) && $var $operator $value)
        return true;
}

if(isAnd(1, 1, '===')) echo 'worked';

Thanks in advance.

Upvotes: 17

Views: 20235

Answers (11)

Manoj Kumar
Manoj Kumar

Reputation: 1

$a = 4;
eval('$condition=($a == 4)?true:false;'); 
if($condition){ echo "Yes"; }else{ echo "No"; }

Upvotes: 0

Akshay Khale
Akshay Khale

Reputation: 8361

Here is a simple solution which should work for almost all the operators

Eg.

$b = 10;
$c = '+';
$p = $a . $c. $b; // Forming a String equation
$p = eval('return '.$p.';'); // Evaluating the Equation
echo $p;

Output:

15

Another example with comparison operator:

$b = 10;
$c = '==';
$p = $a . $c. $b;
$p = eval('return '.$p.';');
echo $p;

Output:

false

Hope this helps.

Upvotes: 2

Tarek Adam
Tarek Adam

Reputation: 3525

The top answer recommends a small class, but I like a trait.

trait DynamicComparisons{

private $operatorToMethodTranslation = [
    '=='  => 'equal',
    '===' => 'totallyEqual',
    '!='  => 'notEqual',
    '>'   => 'greaterThan',
    '<'   => 'lessThan',
];

protected function is($value_a, $operation, $value_b){

    if($method = $this->operatorToMethodTranslation[$operation]){
        return $this->$method($value_a, $value_b);
    }

    throw new \Exception('Unknown Dynamic Operator.');
}

private function equal($value_a, $value_b){
    return $value_a == $value_b;
}

private function totallyEqual($value_a, $value_b){
    return $value_a === $value_b;
}

private function notEqual($value_a, $value_b){
    return $value_a != $value_b;
}

private function greaterThan($value_a, $value_b){
    return $value_a > $value_b;
}

private function lessThan($value_a, $value_b){
    return $value_a < $value_b;
}

private function greaterThanOrEqual($value_a, $value_b){
    return $value_a >= $value_b;
}

private function lessThanOrEqual($value_a, $value_b){
    return $value_a <= $value_b;
}

}

Upvotes: 10

Goran
Goran

Reputation: 281

How about this one?

function num_cond ($var1, $op, $var2) {

    switch ($op) {
        case "=":  return $var1 == $var2;
        case "!=": return $var1 != $var2;
        case ">=": return $var1 >= $var2;
        case "<=": return $var1 <= $var2;
        case ">":  return $var1 >  $var2;
        case "<":  return $var1 <  $var2;
    default:       return true;
    }   
}

Test:

$ops = array( "=", "!=", ">=", "<=", ">", "<" );
$v1 = 1; $v2 = 5;

foreach ($ops as $op) {
    if (num_cond($v1, $op, $v2)) echo "True  ($v1 $op $v2)\n"; else echo "False ($v1 $op $v2)\n";
}

Upvotes: 28

alokin
alokin

Reputation: 451

You can also use version_compare() function, as you can pass operator which will be used for comparison as third argument.

Upvotes: 45

deceze
deceze

Reputation: 522016

The bigger problem is that this function is pretty pointless. Let's replace that with a real (hypothetically working) example:

function isAnd($var, $value, $operator = '==') {
    return isset($var) && $var $operator $value;
}

isAnd($foo, 1, '===');

In this example $foo is not set. You'll get an error because you're trying to pass a non-existent variable ($foo) to a function (isAnd). So, you will need to test $foo for isset before calling isAnd:

isset($foo) && isAnd($foo, 1, '===');

So, any variable that ever enters the isAnd function is definitely set. You don't need to test for it inside the function. So the whole exercise is pretty pointless.

What may be confusing is that isset() and empty() don't have this limitation, i.e. you can pass a non-existent variable to them without error. The thing is though, these are not normal functions, they're special language constructs (that happen to look like functions; blame PHP). Unfortunately you can not make these kinds of constructs, parameters for your functions always need to exist.

You should just get used to writing isset($foo) && $foo === 1. With properly structured code, you can reduce this to a minimum by always declaring all variables you're going to use, which is good practice anyway.

For the dynamic operator... you'll need some form of if ... else somewhere to decide which operator to use anyway. Instead of setting the operator variable and then evaluating it, isn't it easier to do the evaluation right there?

Upvotes: 3

symcbean
symcbean

Reputation: 48357

As Michael Krelin suggests you could use eval - but that potentially enables a lot of code injection attacks.

You can't substitute a variable for an operator - but you can substitute a variable for a function:

function is_equal($a, $b) {
  return $a==$b;
} 
function is_same($a, $b) {
  return $a===$b;
}
function is_greater_than($a, $b)
....

$compare='is_equal';
if ($compare($a, $b)) {
   ....

C.

Upvotes: 1

giftnuss
giftnuss

Reputation: 529

How about a small class:

class compare
{
  function is($op1,$op2,$c)
  {
     $meth = array('===' => 'type_equal', '<' => 'less_than');
     if($method = $meth[$c]) {
        return $this->$method($op1,$op2);
     }
     return null; // or throw excp.
  }
  function type_equal($op1,$op2)
  {
      return $op1 === $op2;
  }
  function less_than($op1,$op2)
  {
      return $op1 < $op2;
  }
}

Upvotes: 11

snowflake
snowflake

Reputation: 1714

As far as I know it is not possible and since there is no reference about callback on operators in PHP documentation, http://www.php.net/manual/en/language.operators.php

instead of using eval, I would redefine each operators in global functions and use php callbacks How do I implement a callback in PHP?

Upvotes: 0

Michael Krelin - hacker
Michael Krelin - hacker

Reputation: 143051

If you absolutely insist you can use eval.

if(isset($var) && eval("return \$var $operator \$value"))
    return true;

But I wouldn't recommend it.

Upvotes: 2

Your Common Sense
Your Common Sense

Reputation: 157839

No, it's impossible. You can use conditional operators instead, but it will be much,much better if you redesign your application to make such a dynamic comparison unnecessary.

Upvotes: -3

Related Questions