2010-05-27 173 views
10

是否有可能以任何方式将比较运算符作为变量传递给函数?例如(我知道这是行不通的):PHP中的动态比较运算符

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

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

在此先感谢。

+2

什么是这样的功能的呢?函数调用比操作本身长得多,我想不出有用的东西。 – soulmerge 2010-05-27 08:10:57

+1

如果您使用Scheme,您可以。它可以是一个非常强大的模式。 – Skilldrick 2010-05-27 08:13:49

回答

9

怎么样小类:

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

我甚至没有想到使用类,早上也许太早了一些解释?谢谢。 – BenTheDesigner 2010-05-27 08:38:33

+7

它为什么需要成为一个班级? – symcbean 2010-05-27 12:35:15

+0

5.3之前这是最好的选择,命名空间和真正的回调可能是其他好的解决方案。但是一门课可能是最简单的一门课。 – giftnuss 2010-06-10 16:37:56

-2

不,这是不可能的。 您可以使用条件运算符来代替,但如果您重新设计应用程序以使这种动态比较变得不必要,那么它将会更好,更好

2

如果你绝对坚持你可以使用eval。

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

但我不会推荐它。

+8

+1 - 但你为什么不推荐它可能是有价值的读者 – symcbean 2010-05-27 12:31:07

2

更大的问题是,这个功能是非常没有意义的。让我们来替换成一个真正的(假设工作)例如:

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

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

在这个例子中$foo未设置。由于您试图将不存在的变量($foo)传递给某个函数(isAnd),因此会出现错误。所以,你需要调用isAnd之前测试$fooisset

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

所以,曾经进入isAnd功能的变量肯定是设置。你不需要在函数内测试它。所以整个练习都是毫无意义的。

可能令人困惑的是isset()empty()没有这个限制,即你可以传递一个不存在的变量给它们,没有错误。但事情是,这些不是普通的函数,它们是特殊的语言结构(它看起来像函数;责怪PHP)。不幸的是不能使这些类型的结构,你的函数的参数总是需要存在。

你应该习惯写作isset($foo) && $foo === 1。使用结构合理的代码,通过始终声明所有要使用的变量,可以将其降至最低,无论如何,这是一个很好的做法。

对于动态操作符...您需要某种形式的if ... else某处来决定要使用哪个操作符。而不是设置运营商变量,然后评估它,是不是更容易做那里的评估?

+0

另见相关http://stackoverflow.com/questions/1960509/isset-and-empty-make-code-ugly/1960588#1960588 – deceze 2010-05-27 08:14:38

1

由于Michael Krelin建议您可以使用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.

22

您还可以使用version_compare()功能,你可以通过运营商这将作为第三个参数用于比较。

+1

天才。 +1这是一个非常有创意的解决方案,适用于数字比较。 – 2011-10-17 20:46:32

+0

下面是例子,'if(version_compare(5.9,6,'<='))echo TRUE; //返回1' – 2016-02-02 06:29:15

+0

我实际上正在创建一个自己的版本比较函数,因为我不知道PHP有这个函数,真棒! – 2016-06-02 18:15:21

11

这件怎么样?

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"; 
} 
+0

你应该在你的测试中包含输入/输出。 – 2012-11-25 09:17:16

+0

这是非常好的主意,我在我的code.thanks中使用了这个 – 2013-12-30 20:06:15

2

顶端回答建议小班,但我喜欢的性状。

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

}