ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

我不知道“猫王”这个名字。为此+1。

M
Mark Amery

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

在伪代码中,

foo = bar ?: baz;

大致解决为

foo = bar ? bar : baz;

或者

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

不同之处在于 bar 只会被评估一次。

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

foo = foo ?: bar;

如果 foo 为 null 或 false,这会将 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

https://i.stack.imgur.com/hQlrps.png


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

请参阅the docs

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


TBH,文档是正确的。 expr2 发生的事情是它只是消失了,并且没有被评估。 $this->expensiveComputation() ?: "nope"$this->expensiveComputation() ? $this->expensiveComputation() : "nope" 不同 - expr1 只计算一次。
M
Martin

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

  $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 不!这使得 Elvis 运算符在 PHP imo 中毫无用处。 Elvis 运算符对表达式求值,如果为真,则返回它,否则返回最后一部分。由于 PHP 是低类型的,所以很多事情都是真或假,而且很可能不是你想要的。即:如果未定义变量,您想为变量设置默认值,使用 Elvis 运算符 PHP 会说未定义 0,但您可能想要 0...这就是 PHP 7 将获得 Null Coalesce 运算符的原因, 它会严格测试你的变量是否为空,所以 PHP 会说 0 不是未定义的。
而不是 isset($arr[$key]) 有人可以使用 @$arr[$key] 语法
@FuscaSoftware:根据我的经验,使用这样的错误抑制不是一个好主意。
k
kaznovac

猫王运营商:

?: 是 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

何时使用:

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

$testedVar ? $testedVar : $otherVar;

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

$testedVar ?: $otherVar;

请注意,空数组的计算结果也为 false。 var_dump([] ?: 'Expression not true'); 为您提供“表达式不正确”。因此,elvis 运算符有点像检查 empty(),而空合并运算符 (??) 更像是测试 isset()
P
Prasad Paradkar

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

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


A
Atli

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