Я споткнулся об операторе if, использующем оператор PHP null coalesce, не ведущий себя как «ожидаемый». Рассматриваемый код выглядит примерно так:
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)
Теперь то, что я думаю, происходит в тесте №. 3, он исполняется как
$test['baz'] ?? (null || $test['foobar']) ?? null
, поэтому, если $test['baz']
оценивается как unset (что он, очевидно, делает), следующий null || $test['foobar']
get выполняется, что приводит к $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)
, что может указывать, приведенный выше пример - правильное поведение.
Что ты думаешь? Должно ли это быть сообщено как ошибка? Я знаю, что это не «правильный» вопрос, однако, так как я не смог найти сообщение об ошибке / обсуждение / ветку об этом, я подумал, что должен быть ресурс, документирующий это.
Если вы / моды не согласны, я снова сниму вопрос.