【问题标题】:?: operator (the 'Elvis operator') in PHP?: PHP 中的运算符(“猫王运算符”)
【发布时间】:2010-12-31 21:26:34
【问题描述】:

我今天在一些 PHP 代码中看到了这一点:

$items = $items ?: $this->_handle->result('next', $this->_result, $this);

我不熟悉这里使用的?: 运算符。它看起来像一个三元运算符,但如果谓词为真,则评估的表达式已被省略。什么意思?

【问题讨论】:

    标签: php conditional-operator language-construct


    【解决方案1】:

    the docs:

    从 PHP 5.3 开始,可以省略三元运算符的中间部分。如果expr1 的计算结果为TRUE,则表达式expr1 ?: expr3 返回expr1,否则返回expr3

    【讨论】:

    • TBH,文档是正确的。 expr2 发生的事情是它只是消失了,没有被评估。 $this->expensiveComputation() ?: "nope"$this->expensiveComputation() ? $this->expensiveComputation() : "nope" 不同 - expr1 只计算一次。
    【解决方案2】:

    是的,这是 PHP 5.3 中的新功能。如果它被评估为 TRUE,则返回测试表达式的值,如果被评估为 FALSE,则返回替代值。

    【讨论】:

      【解决方案3】:

      如果左操作数是truthy,则计算左操作数,否则计算右操作数。

      在伪代码中,

      foo = bar ?: baz;
      

      大致解析为

      foo = bar ? bar : baz;
      

      if (bar) {
          foo = bar;
      } else {
          foo = baz;
      }
      

      区别在于bar 只会被评估一次。

      您还可以使用它对foo 进行“自检”,如您发布的代码示例所示:

      foo = foo ?: bar;
      

      如果foo 为空或错误,这会将bar 分配给foo,否则它将保持foo 不变。

      更多示例:

      <?php
          var_dump(5 ?: 0); // 5
          var_dump(false ?: 0); // 0
          var_dump(null ?: 'foo'); // 'foo'
          var_dump(true ?: 123); // true
          var_dump('rock' ?: 'roll'); // 'rock'
      ?>
      

      顺便说一下,它叫做Elvis operator

      【讨论】:

      • 请确保括号中的变量存在,否则您将引发错误。 PHP 不会仅仅假设它的值为null 或任何值。只是说'
      • 为什么不直接使用||。那么blah || 'default'?
      • @Noitidart 因为,与在 JS 中返回最左边的真实操作数不同,在 PHP 中,|| 运算符总是返回一个布尔值。
      • 对于任何想知道的人来说,空字符串是错误的,所以 var_dump('' ?: 'foo'); 将是 foo
      【解决方案4】:

      小心使用数组。我们必须在?之后写一个检查变量,因为:

        $params = ['param1' => 'value1',
                   'param2' => 'value2',
                   'param3' => 'value3',];
      
        $param1 = isset($params['param1'])?:null;
        $param2 = !empty($params['param2'])?:null;
        $param3 = $params['param3']?:null; // get E_NOTICE, if $params['param3'] eq false
      
        var_dump($param1,$param2,$param3);
        true // would like to expect `value1`
        true // would like to expect `value2`
        param3 // properly, but problem above
      

      更新

      来自 RFC。在 PHP 7 中,运算符 Null Coalesce Operator 将执行此操作,例如:

      $param1 = $params['param1'] ?? null;
      // Equivalent to:  $param1 = isset($params['param1']) ? $params['param1'] : null;
      

      【讨论】:

      • 所以 null coalesce 和 elvis 是一样的吗?
      • @NabeelKhan 不!这使得 Elv​​is 运算符在 PHP imo 中毫无用处。 Elvis 运算符对表达式求值,如果为真,则返回它,否则返回最后一部分。由于 PHP 是低类型的,很多事情都是对的,也可能是错的,而且很可能不是你想要的。即:如果未定义变量,您想为变量设置默认值,使用 Elvis 运算符 PHP 会说未定义 0,但您可能想要 0...这就是 PHP 7 将获得 Null Coalesce 运算符的原因, 它会严格测试你的变量是否为 null,所以 PHP 会说 0 不是未定义的。
      • 而不是 isset($arr[$key]) 有人可以使用 @$arr[$key] 语法
      • @FuscaSoftware :根据我的经验,使用这样的错误抑制不是一个好主意。
      【解决方案5】:

      另一个重要的考虑因素:Elvis Operator 打破了 Zend Opcache 标记化过程。我发现这很难!虽然这可能已在以后的版本中得到修复,但我可以确认 PHP 5.5.38 中存在此问题(内置 Zend Opcache v7.0.6-dev)。

      如果您发现您的某些文件“拒绝”缓存在 Zend Opcache 中,这可能是原因之一...希望这会有所帮助!

      【讨论】:

        【解决方案6】:

        猫王操作员:

        ?: 是 Elvis 运算符。这是一个二元运算符,它执行以下操作:

        ?: 的左侧值强制为布尔值并检查它是否为true。如果true 会返回左边的表达式,如果是false 会返回右边的表达式。

        示例:

        var_dump(0 ?: "Expression not true");     // expression returns: Expression not true
        var_dump("" ?: "Expression not true");    // expression returns: Expression not true
        var_dump("hi" ?: "Expression not true");  // expression returns string hi
        var_dump(null ?: "Expression not true");  // expression returns: Expression not true
        var_dump(56 ?: "Expression not true");    // expression return int 56
        

        何时使用:

        猫王运算符基本上是三元运算符特定情况的简写语法,即:

        $testedVar ? $testedVar : $otherVar;
        

        Elvis 运算符将通过以下方式使语法更加简洁:

        $testedVar ?: $otherVar;
        

        【讨论】:

          猜你喜欢
          • 2018-09-26
          • 1970-01-01
          • 2022-10-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-13
          相关资源
          最近更新 更多