这是 PHP 空合并运算符中的错误还是预期行为?
Is this a bug in PHP null coalesce operator or expected behaviour?
我偶然发现了一个 if 语句,它使用 PHPs 空合并运算符,而不是 "expected"。有问题的代码看起来像这样:
if ($foo['bar'] ?? false || $foo['baz'] ?? false) { /* ... */ }
改为
if (($foo['bar'] ?? false) || ($foo['baz'] ?? false)) { /* ... */ }
解决了。
我 运行 在我的终端中进行快速测试:
root@docker:/application# php -v
PHP 7.2.11-2+ubuntu18.04.1+deb.sury.org+1 (cli) (built: Oct 15 2018 11:40:35) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.2.11-2+ubuntu18.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies
with Xdebug v2.6.1, Copyright (c) 2002-2018, by Derick Rethans
root@docker:/application# php -a
Interactive mode enabled
php > $test = ['foo' => 'bar'];
php > var_dump($test['baz'] ?? null); // as expected
php shell code:1:
NULL
php > var_dump(($test['baz'] ?? null)); // as expected
php shell code:1:
NULL
php > var_dump($test['baz'] ?? null || $test['foobar'] ?? null); // as expected, but there's a Notice
PHP Notice: Undefined index: foobar in php shell code on line 1
PHP Stack trace:
PHP 1. {main}() php shell code:0
php shell code:1:
bool(false)
php > var_dump(($test['baz'] ?? null) || ($test['foobar'] ?? null)); // as expected
php shell code:1:
bool(false)
现在,我认为在第 1 号测试中会发生什么。 3, 是它被执行为
$test['baz'] ?? (null || $test['foobar']) ?? null
因此,如果 $test['baz']
的计算结果为未设置(显然确实如此),则下一个 null || $test['foobar']
将被执行,这会导致 $test['foobar']
抛出通知。
我的问题:这是 PHP 中空合并运算符的预期行为吗?我有点希望它比 ||
(或)运算符的绑定更强。
另一方面,在 RFC (https://wiki.php.net/rfc/isset_ternary) 中,有一个明确的示例:
var_dump(0 || 2 ?? 3 ? 4 : 5); // ((0 || 2) ?? 3) ? 4 : 5 => int(4)
这可能表明,上面的示例是正确的行为。
你怎么看?这应该被报告为错误吗?我知道这不是一个 "proper" 问题,但是由于我找不到关于它的错误 report/discussion/thread,我认为应该有一个资源记录它。
如果 you/the 版主不同意,我会再次删除问题。
,这是预期的行为
||
的优先级高于 ??
,因此您的原始语句被视为
if ($foo['bar'] ?? (false || $foo['baz']) ?? false)
我偶然发现了一个 if 语句,它使用 PHPs 空合并运算符,而不是 "expected"。有问题的代码看起来像这样:
if ($foo['bar'] ?? false || $foo['baz'] ?? false) { /* ... */ }
改为
if (($foo['bar'] ?? false) || ($foo['baz'] ?? false)) { /* ... */ }
解决了。
我 运行 在我的终端中进行快速测试:
root@docker:/application# php -v
PHP 7.2.11-2+ubuntu18.04.1+deb.sury.org+1 (cli) (built: Oct 15 2018 11:40:35) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.2.11-2+ubuntu18.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies
with Xdebug v2.6.1, Copyright (c) 2002-2018, by Derick Rethans
root@docker:/application# php -a
Interactive mode enabled
php > $test = ['foo' => 'bar'];
php > var_dump($test['baz'] ?? null); // as expected
php shell code:1:
NULL
php > var_dump(($test['baz'] ?? null)); // as expected
php shell code:1:
NULL
php > var_dump($test['baz'] ?? null || $test['foobar'] ?? null); // as expected, but there's a Notice
PHP Notice: Undefined index: foobar in php shell code on line 1
PHP Stack trace:
PHP 1. {main}() php shell code:0
php shell code:1:
bool(false)
php > var_dump(($test['baz'] ?? null) || ($test['foobar'] ?? null)); // as expected
php shell code:1:
bool(false)
现在,我认为在第 1 号测试中会发生什么。 3, 是它被执行为
$test['baz'] ?? (null || $test['foobar']) ?? null
因此,如果 $test['baz']
的计算结果为未设置(显然确实如此),则下一个 null || $test['foobar']
将被执行,这会导致 $test['foobar']
抛出通知。
我的问题:这是 PHP 中空合并运算符的预期行为吗?我有点希望它比 ||
(或)运算符的绑定更强。
另一方面,在 RFC (https://wiki.php.net/rfc/isset_ternary) 中,有一个明确的示例:
var_dump(0 || 2 ?? 3 ? 4 : 5); // ((0 || 2) ?? 3) ? 4 : 5 => int(4)
这可能表明,上面的示例是正确的行为。
你怎么看?这应该被报告为错误吗?我知道这不是一个 "proper" 问题,但是由于我找不到关于它的错误 report/discussion/thread,我认为应该有一个资源记录它。
如果 you/the 版主不同意,我会再次删除问题。
||
的优先级高于 ??
,因此您的原始语句被视为
if ($foo['bar'] ?? (false || $foo['baz']) ?? false)