PHP-тернарный оператор против оператора нулевой коалесценции
Может ли кто-нибудь объяснить различия между сокращением тернарных операторов ( ?:
🙂 И нулевым коалесцирующим оператором ( ??
) в PHP?
Когда они ведут себя по-разному и когда одинаково (если это вообще происходит)?
$a ?: $b
VS.
- Как использовать тернарный оператор внутри интерполированной строки?
- Неожиданный тип, полученный от тройного оператора
- Тернарный оператор - JAVA
- Почему тройной оператор неожиданно накладывает целые числа?
- Как работает тройной оператор?
$a ?? $b
Когда ваш первый аргумент равен NULL, они в основном одинаковы, за исключением того, что нулевой коалесцинг не E_NOTICE
если у вас есть неопределенная переменная. В документах по миграции PHP 7.0 есть следующее:
Нулевой коалесцирующий оператор (??) был добавлен в качестве синтаксического сахара для общего случая необходимости использования тройной связи с isset (). Он возвращает свой первый операнд, если он существует, и не является NULL; в противном случае он возвращает свой второй операнд.
Вот пример кода, демонстрирующий это:
null); print $b['a'] ?? 'd'; print "\n"; print $b['a'] ?: 'd'; print "\n"; print $b['c'] ?? 'e'; print "\n"; print $b['c'] ?: 'e'; print "\n";
И это результат:
b b a Notice: Undefined variable: c in /in/apAIb on line 14 a d d e Notice: Undefined index: c in /in/apAIb on line 33 e
Линии, у которых есть уведомление, являются те, где я использую сокращенный тернарный оператор, а не нулевой оператор коалесценции. Однако даже с уведомлением PHP даст тот же ответ.
Выполните код: https://3v4l.org/McavC
Конечно, это всегда предполагает, что первый аргумент равен null
. Как только он больше не является нулевым, тогда вы получите разницу в том, что ??
оператор всегда будет возвращать первый аргумент, в то время как сокращение ?:
будет только в том случае, если первый аргумент был правдоподобным, и он полагается на то, как PHP будет вводить типы в булевское .
Так:
$a = false ?? 'f'; $b = false ?: 'g';
тогда будет иметь значение $a
равное false
и $b
равное 'g'
.
Если вы используете так называемый краткий оператор shortcut, это вызовет уведомление, если $_GET['username']
не задано:
$val = $_GET['username'] ?: 'default';
Поэтому вместо этого вы должны сделать что-то вроде этого:
$val = isset($_GET['username']) ? $_GET['username'] : 'default';
Оператор нулевой коалесценции эквивалентен приведенному выше утверждению и возвращает значение «по умолчанию», если $_GET['username']
не задано или равно null
:
$val = $_GET['username'] ?? 'default';
Обратите внимание, что он не проверяет правдоподобие . Он проверяет, только если он установлен и не равен нулю.
Вы также можете сделать это, и будет возвращено первое определенное (установленное, а не null
) значение:
$val = $input1 ?? $input2 ?? $input3 ?? 'default';
Теперь это правильный коалесцирующий оператор.
Основное различие заключается в том, что
-
Терминальное выражение оператора
expr1 ?: expr3
возвращаетexpr1
еслиexpr1
значениеTRUE
но, с другой стороны, выражение Null Coalescing Operator(expr1) ?? (expr2)
(expr1) ?? (expr2)
вычисляетexpr1
еслиexpr1
не являетсяNULL
-
Терминальный оператор
expr1 ?: expr3
испускает уведомление, если значение левой стороны(expr1)
не существует, но, с другой стороны, Null Coalescing Operator(expr1) ?? (expr2)
(expr1) ?? (expr2)
В частности, не выделяет уведомление, если значение левой стороны(expr1)
не существует, какisset()
. -
ТернарОператор оставлен ассоциативным
((true ? 'true' : false) ? 't' : 'f');
Оператор Null Coalescing является правильным ассоциативным
($a ?? ($b ?? $c));
Теперь давайте объясним разницу между примером:
Тернарный оператор (?:)
$x=''; $value=($x)?:'default'; var_dump($value); // The above is identical to this if/else statement if($x){ $value=$x; } else{ $value='default'; } var_dump($value);
по$x=''; $value=($x)?:'default'; var_dump($value); // The above is identical to this if/else statement if($x){ $value=$x; } else{ $value='default'; } var_dump($value);
по$x=''; $value=($x)?:'default'; var_dump($value); // The above is identical to this if/else statement if($x){ $value=$x; } else{ $value='default'; } var_dump($value);
Оператор Null Coalescing (??)
$value=($x)??'default'; var_dump($value); // The above is identical to this if/else statement if(isset($x)){ $value=$x; } else{ $value='default'; } var_dump($value);
по$value=($x)??'default'; var_dump($value); // The above is identical to this if/else statement if(isset($x)){ $value=$x; } else{ $value='default'; } var_dump($value);
по$value=($x)??'default'; var_dump($value); // The above is identical to this if/else statement if(isset($x)){ $value=$x; } else{ $value='default'; } var_dump($value);
Вот таблица, объясняющая разницу и сходство между '??'
и ?:
Специальное примечание. Оператор коалесценции и тернарный оператор являются выражением и что он не оценивает переменную, а результат выражения. Это важно знать, хотите ли вы вернуть переменную по ссылке. Утверждение возвращает $ foo ?? $ Бар; и вернуть $ var == 42? $ a: $ b; в функции возврата-ссылки не будет работать и выдается предупреждение.
Оба они ведут себя по-разному, когда речь идет о динамической обработке данных.
Если переменная пуста (”), нулевой коалесцинг будет обрабатывать переменную как истину, но сокращенный тернарный оператор не будет. И это то, что нужно иметь в виду.
$a = NULL; $c = ''; print $a ?? '1b'; print "\n"; print $a ?: '2b'; print "\n"; print $c ?? '1d'; print "\n"; print $c ?: '2d'; print "\n"; print $e ?? '1f'; print "\n"; print $e ?: '2f';
И выход:
1b 2b 2d 1f Notice: Undefined variable: e in /in/ZBAa1 on line 21 2f
Ссылка: https://3v4l.org/ZBAa1
Разработайте ниже в интерактивном режиме php -a
( php -a
на терминале). Комментарий к каждой строке показывает результат.
var_dump (false ?? 'value2'); # bool(false) var_dump (true ?? 'value2'); # bool(true) var_dump (null ?? 'value2'); # string(6) "value2" var_dump ('' ?? 'value2'); # string(0) "" var_dump (0 ?? 'value2'); # int(0) var_dump (false ?: 'value2'); # string(6) "value2" var_dump (true ?: 'value2'); # bool(true) var_dump (null ?: 'value2'); # string(6) "value2" var_dump ('' ?: 'value2'); # string(6) "value2" var_dump (0 ?: 'value2'); # string(6) "value2"
Итак, это моя интерпретация:
1. Оператор Null Coalescing – ??
:
-
??
как «ворота», который пропускает только NULL . - Таким образом, он всегда возвращает первый параметр , если первый параметр не имеет значения
NULL
. - Это означает
??
такое же, как( !isset() || is_null() )
2. Тернарный оператор – ?:
-
?:
как ворота, которые пропускаютanything falsy
– включаяNULL
-
0
,empty string
,NULL
,false
!isset()
,empty()
.. все, что пахнет ложью - Как и classический тернарный оператор:
echo ($x ? $x : false)
- ПРИМЕЧАНИЕ:
?:
ВыдаетPHP NOTICE
на неопределенные (unset
или!isset()
) переменные
3. Итак, доктор, когда я использую ??
и ?:
..
- Я просто шучу – я не доктор, и это всего лишь интерпретация
- Я бы использовал
?:
Когда- выполнение
empty($x)
проверок - Классическая тройная операция типа
!empty($x) ? $x : $y
!empty($x) ? $x : $y
можно сократить до$x ?: $y
-
if(!$x) { fn($x); } else { fn($y); }
if(!$x) { fn($x); } else { fn($y); }
можно укоротить доfn(($x ?: $y))
- выполнение
- Я бы использовал
??
когда- Я хочу сделать
!isset() || is_null()
!isset() || is_null()
- например, проверить, существует ли объект –
$object = $object ?? new objClassName();
$object = $object ?? new objClassName();
- Я хочу сделать
4. Операторы стекирования …
-
Тернарный оператор может быть уложен в стопку …
echo 0 ?: 1 ?: 2 ?: 3; //1 echo 1 ?: 0 ?: 3 ?: 2; //1 echo 2 ?: 1 ?: 0 ?: 3; //2 echo 3 ?: 2 ?: 1 ?: 0; //3 echo 0 ?: 1 ?: 2 ?: 3; //1 echo 0 ?: 0 ?: 2 ?: 3; //2 echo 0 ?: 0 ?: 0 ?: 3; //3
Источник и кредит для этого кода
Это в основном последовательность:
if( truthy ) {} else if(truthy ) {} else if(truthy ) {} .. else {}
-
Оператор Null Coalese может быть уложен …
$v = $x ?? $y ?? $z;
Это последовательность:
if(!isset($x) || is_null($x) ) {} else if(!isset($y) || is_null($y) ) {} else {}
-
Используя укладку, я могу сократить это:
if(!isset($_GET['name'])){ if(isset($user_name) && !empty($user_name)){ $name = $user_name; }else { $name = 'anonymous'; } } else { $name = $_GET['name']; }
К этому:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
Круто, правда? 🙂
Прокрутите вниз по этой ссылке и просмотрите раздел, это дает вам сравнительный пример, как показано ниже:
Тем не менее, не рекомендуется связывать операторов, так как это затрудняет понимание кода при чтении позже.
Нулевой коалесцирующий оператор (??) был добавлен в качестве синтаксического сахара для общего случая необходимости использования тройной связи с isset (). Он возвращает свой первый операнд, если он существует, и не является NULL; в противном случае он возвращает свой второй операнд.
По сути, использование оператора коалесценции автоматически проверяет значение null в отличие от тернарного оператора.
Кажется, есть плюсы и минусы использования либо ??
или ?:
. Про использовать ?:
том, что он оценивает значение false и null и “” то же самое. Кон является то, что он сообщает E_NOTICE, если предыдущий аргумент равен null. С ??
pro заключается в отсутствии E_NOTICE, но con – это то, что он не оценивает false и null то же самое. По моему опыту, я видел, что люди начинают использовать нулевые и ложные взаимозаменяемые, но затем они в конечном итоге прибегают к модификации своего кода, чтобы быть совместимыми с использованием либо нулевого, либо ложного, но не того и другого. Альтернативой является создание более сложного тернарного состояния: (isset($something) or !$something) ? $something : $something_else
(isset($something) or !$something) ? $something : $something_else
.
Ниже приведен пример различия в использовании оператор, использующий как null, так и false:
$false = null; $var = $false ?? "true"; echo $var . "---
";//returns: true--- $false = false; $var = $false ?? "true"; echo $var . "---
"; //returns: ---
Однако, разрабатывая троичный оператор, мы можем сделать ложную или пустую строку «», как если бы это был нуль, не выбрасывая e_notice:
$false = null; $var = (isset($false) or !$false) ? $false : "true"; echo $var . "---
";//returns: --- $false = false; $var = (isset($false) or !$false) ? $false : "true"; echo $var . "---
";//returns: --- $false = ""; $var = (isset($false) or !$false) ? $false : "true"; echo $var . "---
";//returns: --- $false = true; $var = (isset($false) or !$false) ? $false : "true"; echo $var . "---
";//returns: 1---
Лично я думаю, было бы очень приятно, если бы в будущем rev PHP включался новый оператор :?
который заменил вышеупомянутый синтаксис. ie: // $var = $false :? "true";
// $var = $false :? "true";
Этот синтаксис будет оценивать значение null, false и “” одинаково, а не генерировать E_NOTICE …
class a { public $a = 'aaa'; } $a = new a(); echo $a->a; // Writes 'aaa' echo $a->b; // Notice: Undefined property: a::$b echo $a->a ?? '$a->a does not exists'; // Writes 'aaa' // Does not throw an error although $a->b does not exist. echo $a->b ?? '$a->b does not exist.'; // Writes $a->b does not exist. // Does not throw an error although $a->b and also $a->b->c does not exist. echo $a->b->c ?? '$a->b->c does not exist.'; // Writes $a->b->c does not exist.
Null Coalescing operator
выполняет только две задачи: он проверяет, установлена whether the variable is set
whether it is null
. Взгляните на следующий пример:
с
В приведенном выше примере кода указано, что Null Coalescing operator
обрабатывает несуществующую переменную и переменную, которая равна NULL
таким же образом.
Null Coalescing operator
является улучшением по сравнению с ternary operator
. Посмотрите следующий fragment кода, сравнивающий два:
Таким образом, разница между ними заключается в том, что Null Coalescing operator
оператора Null Coalescing operator
предназначен для обработки неопределенных переменных лучше, чем ternary operator
. Принимая во внимание, что ternary operator
является сокращением для if-else
.
Null Coalescing operator
не предназначен для замены ternary operator
, но в некоторых случаях использования, как в приведенном выше примере, он позволяет писать чистый код с меньшими затратами.
Кредиты: http://dwellupper.io/post/6/php7-null-coalescing-operator-usage-and-examples