PHP中的?:运算符('Elvis运算符')

alp*_*uno 240 php coding-style language-construct conditional-operator

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

$items = $items ?: $this->_handle->result('next', $this->_result, $this);
Run Code Online (Sandbox Code Playgroud)

我不熟悉?:这里使用的运算符.它看起来像一个三元运算符,但是省略了判断谓词是否为真的表达式.这是什么意思?

Bal*_*usC 483

如果左操作数是真值则计算左操作数,否则计算右操作数.

在伪代码中,

foo = bar ?: baz;
Run Code Online (Sandbox Code Playgroud)

大致解决了

foo = bar ? bar : baz;
Run Code Online (Sandbox Code Playgroud)

要么

if (bar) {
    foo = bar;
} else {
    foo = baz;
}
Run Code Online (Sandbox Code Playgroud)

差异bar只会被评估一次.

您也可以使用它来进行"自检",foo如您发布的代码示例中所示:

foo = foo ?: bar;
Run Code Online (Sandbox Code Playgroud)

这将分配barfoo是否foo为空或falsey,否则会留下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'
?>
Run Code Online (Sandbox Code Playgroud)

顺便说一句,它被称为猫王运营商.

猫王经营者

  • 操作少一点,请多一点表达. (37认同)
  • 有趣的是,这个答案与Wiki文章形成了一个递归循环,但没有完全解释为什么它被称为"Elvis运算符". (20认同)
  • 确保括号中的变量存在,否则您将引发错误.PHP不会假设它具有"null"或任何值.只是在说' (11认同)
  • @Noitidart因为,与JS不同,它返回最左边的truthy操作数,在PHP中,`||`运算符总是返回一个布尔值. (7认同)
  • 为什么不直接使用`||`。所以`blah || '默认'`? (3认同)
  • 对于任何想知道的人来说,空字符串是错误的,因此 `var_dump('' ?: 'foo');` 将是 `foo` (2认同)

Yac*_*oby 55

查看文档:

从PHP 5.3开始,可以省略三元运算符的中间部分.如果求值,则expr1 ?: expr3返回表达式,否则返回.expr1expr1TRUEexpr3

  • 他们需要一个新的文档作者,因为不可避免地会有人会问expr2发生了什么.我只是把它搞砸了. (9认同)
  • 有没有搞错?在升级到PHP 7之后,我现在就发现了这一点?我可能已经使用了多年! (4认同)
  • TBH,文档是正确的。`expr2` 发生的事情是它消失了,并且没有被评估。`$this-&gt;expenseComputation() ?: "nope"` 与 `$this-&gt;expenseComputation() 不一样?$this-&gt;expenseComputation() : "nope"` - expr1 只计算一次。 (2认同)

voo*_*417 18

小心阵列.之后我们必须写一个检查变量?,因为:

  $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
Run Code Online (Sandbox Code Playgroud)

更新

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

$param1 = $params['param1'] ?? null;
// Equivalent to:  $param1 = isset($params['param1']) ? $params['param1'] : null;
Run Code Online (Sandbox Code Playgroud)

  • @Mark Amery嗯..真的吗?不是很有帮助吗?您是否真的使用过PHP并查看了使用三元组访问数组变量的数千个案例?好的,我将文本更改为"小心数组......" (7认同)
  • @NabeelKhan不!这使得Elvis运算符在PHP imo中毫无用处.Elvis运算符计算表达式,如果是,则返回它,否则返回最后一部分.由于PHP是低类型的,很多东西都是真的,或者是假的,很可能事情不会是你想要的.即:如果没有定义变量,你想要为变量设置一个默认值,使用Elvis运算符PHP会说0没有定义,但是你可能想要0 ...这就是PHP 7将获得Null Coalesce运算符的原因,它会严格测试你的变量为null,所以PHP会说0不是未定义的. (7认同)
  • @FuscaSoftware :根据我的经验,使用这样的错误抑制并不是一个好主意。 (2认同)

Wil*_*een 18

埃尔维斯操作员:

?:是埃尔维斯算子。这是一个二元运算符,它执行以下操作:

将 的 left 值强制转换?:为布尔值并检查它是否为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
Run Code Online (Sandbox Code Playgroud)

何时使用:

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

$testedVar ? $testedVar : $otherVar;
Run Code Online (Sandbox Code Playgroud)

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

$testedVar ?: $otherVar;
Run Code Online (Sandbox Code Playgroud)


小智 7

另一个重要的考虑因素:Elvis运营商打破了Zend Opcache令牌化过程.我发现这很难!虽然这可能已在更高版本中修复,但我可以确认PHP 5.5.38中存在此问题(使用内置的Zend Opcache v7.0.6-dev).

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