Операторы динамического сравнения в PHP

Можно ли каким-либо образом передать операторы сравнения в качестве переменных в функцию? Например, я ищу некоторые функции удобства (и я знаю, что это не сработает):

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

Заранее спасибо.

Solutions Collecting From Web of "Операторы динамического сравнения в PHP"

Как насчет небольшого класса:

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

Вы также можете использовать функцию version_compare () , так как вы можете передать оператор, который будет использоваться для сравнения в качестве третьего аргумента.

Как насчет этого?

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

Контрольная работа:

 $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"; } 

Если вы абсолютно настаиваете, вы можете использовать eval.

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

Но я бы не рекомендовал его.

Большая проблема заключается в том, что эта функция довольно бессмысленна. Давайте заменим это реальным (гипотетически работающим) примером:

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

В этом примере $foo не задан. Вы получите сообщение об ошибке, потому что пытаетесь передать несуществующую переменную ( $foo ) функции ( isAnd ). Итак, вам нужно будет проверить $foo для isset перед вызовом isAnd :

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

Таким образом, любая переменная, которая когда-либо входит в функцию isAnd определенно задана. Вам не нужно проверять его внутри функции. Таким образом, все упражнение довольно бессмысленно.

Что может сбить с толку, так это то, что isset() и empty() не имеют этого ограничения, то есть вы можете передать несуществующую переменную без ошибок. Дело в том, что это не обычные функции, это специальные языковые конструкции (которые, похоже, выглядят как функции, виноват PHP). К сожалению, вы не можете создавать такие конструкции, параметры для ваших функций всегда должны существовать.

Вы должны просто привыкнуть писать isset($foo) && $foo === 1 . С правильно структурированным кодом вы можете свести это к минимуму, всегда объявляя все переменные, которые вы собираетесь использовать, что является хорошей практикой в ​​любом случае.

Для динамического оператора … вам понадобится какая-то форма if ... else где if ... else нибудь, чтобы решить, какой оператор использовать в любом случае. Вместо того, чтобы устанавливать операторную переменную, а затем оценивать ее, не так ли легко сделать оценку?

Как говорит Майкл Крелин, вы можете использовать eval – но это потенциально позволяет много атак на инъекции кода.

Вы не можете заменить переменную для оператора, но вы можете заменить переменную для функции:

 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.

Верхний ответ рекомендует небольшой класс, но мне нравится черта.

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

Насколько я знаю, это невозможно, и поскольку нет ссылки на обратный вызов для операторов в документации PHP, http://www.php.net/manual/en/language.operators.php

вместо использования eval я бы переопределил каждый оператор в глобальных функциях и использовал обратные вызовы php. Как реализовать обратный вызов в PHP?

Нет, это невозможно. Вместо этого вы можете использовать условные операторы, но это будет намного лучше, если вы перепроектируете свое приложение, чтобы сделать такое динамическое сравнение ненужным.