Операторы динамического сравнения в PHP
Можно ли каким-либо образом передать операторы сравнения в качестве переменных в функцию? Например, я ищу некоторые функции удобства (и я знаю, что это не сработает):
function isAnd($var, $value, $operator = '==')
{
if(isset($var) && $var $operator $value)
return true;
}
if(isAnd(1, 1, '===')) echo 'worked';
Спасибо заранее.
Ответы
Ответ 1
Как насчет небольшого класса:
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;
}
}
Ответ 2
Вы также можете использовать version_compare(), так как вы можете передать оператор, который будет использоваться для сравнения в качестве третьего аргумента.
Ответ 3
Как насчет этого?
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";
}
Ответ 4
Большая проблема заключается в том, что эта функция довольно бессмысленна. Позвольте заменить это реальным (гипотетически работающим) примером:
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
, чтобы решить, какой оператор использовать в любом случае. Вместо того, чтобы устанавливать операторную переменную и затем ее оценивать, не так ли просто сделать оценку там?
Ответ 5
Если вы абсолютно настаиваете на том, что вы можете использовать eval.
if(isset($var) && eval("return \$var $operator \$value"))
return true;
Но я бы не рекомендовал его.
Ответ 6
Верхний ответ рекомендует небольшой класс, но мне нравится черта.
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;
}
}
Ответ 7
Как говорит Майкл Крелин, вы можете использовать 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)) {
....
С.
Ответ 8
Вот простое решение, которое должно работать почти для всех операторов
Например,
$b = 10;
$c = '+';
$p = $a . $c. $b; // Forming a String equation
$p = eval('return '.$p.';'); // Evaluating the Equation
echo $p;
Выход:
15
Еще один пример с оператором сравнения:
$b = 10;
$c = '==';
$p = $a . $c. $b;
$p = eval('return '.$p.';');
echo $p;
Выход:
false
Надеюсь, это поможет.
Ответ 9
Насколько я знаю, это невозможно, и поскольку нет ссылки на обратный вызов для операторов в документации PHP,
http://www.php.net/manual/en/language.operators.php
вместо использования eval я бы переопределил каждый оператор в глобальных функциях и использовал обратные вызовы php
Как реализовать обратный вызов в PHP?
Ответ 10
$a = 4;
eval('$condition=($a == 4)?true:false;');
if($condition){ echo "Yes"; }else{ echo "No"; }
Ответ 11
Нет, это невозможно.
Вместо этого вы можете использовать условные операторы, но он будет намного, гораздо лучше, если вы перепроектируете свое приложение, чтобы сделать такое динамическое сравнение ненужным.