?:PHP中的运算符(“ Elvis运算符”)


257

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

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

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

Answers:


528

如果左操作数为true,则求值为左操作数,否则为右操作数。

用伪代码,

foo = bar ?: baz;

大致解决

foo = bar ? bar : baz;

要么

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

差异bar只会被评估一次。

您还可以使用此方法对foo您发布的代码示例中所示的内容进行“自检” :

foo = foo ?: bar;

这将分配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'
?>

顺便说一下,它被称为Elvis运算符

猫王算子


11
但是请确保括号中的变量存在,否则将引发错误。PHP不仅会假设其值为null或任何值。只是
说说而已

20
有趣的是,这个答案与Wiki文章形成了一个递归循环,但并未完全解释为什么将其称为“猫王运算符”。
hideing.amusing16年

41
少一点操作,请多一点表达。
aalaap

2
为什么不只使用||。那blah || 'default'
Noitidart '18

10
@Noitidart因为与JS中返回最左边的真实操作数的JS不同,在PHP中,||运算符总是返回一个布尔值。
ksadowski

58

文档

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


10
他们需要一个新的文档编写器,因为不可避免地会有人问expr2发生了什么。我只是打它。
约翰·K

7
有没有搞错?我刚刚在升级到PHP 7之后立即发现了这一点?我可能已经使用了多年!
Buttle Butkus

TBH,该文档是正确的。发生的事情expr2是它只是消失了,没有被评估。$this->expensiveComputation() ?: "nope"$this->expensiveComputation() ? $this->expensiveComputation() : "nope"- 不相同-expr1仅评估一次。
Piskvor在

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

更新

来自RFC。将来(在PHP 7中),运算符Null Coalesce Operator将会这样做,例如:

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

1
这并不能回答问题,也对试图了解何时使用Elvis Operator的人没有用。
马克·阿默里

7
@Mark Amery嗯..真的吗?对您没有帮助吗?您是否真的使用过PHP,并且在使用三元访问数组的var时研究过数千种情况?好的,我将文本更改为“小心数组..”
voodoo417

所以空合并和猫王是一样的吗?
纳比尔·汗

7
@NabeelKhan不!这使得Elvis运算符在PHP imo中变得毫无用处。Elvis运算符对一个表达式求值,如果它为真,则返回它,否则返回最后一部分。由于PHP是低类型的,所以很多事情是对还是错,而且很可能不是您想要的。即:如果您想为变量设置默认值(如果未定义),则使用Elvis运算符,PHP会说未定义0,但是您可能希望该值为0 ...这就是为什么PHP 7将获得Null Coalesce运算符的原因,它将严格测试您的变量是否为null,因此PHP会说0不是未定义的。
Gregoire D.

1
@FuscaSoftware:按照我的经验,使用像这样的错误抑制并不是一个好主意。
TeeHays

8

另一个重要的考虑因素:猫王操作员打破了Zend Opcache令牌化过程。我发现这很困难!尽管在更高版本中可能已解决此问题,但是我可以确认PHP 5.5.38(内置Zend Opcache v7.0.6-dev)中存在此问题。

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


4

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


2
轻微错误/误导;两个操作数都不必为布尔值。重要的是第一个值是否真实,而不是TRUE
Mark Amery 2015年

@MarkAmery澄清。用这种方式应该很难误解它。
Atli 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.