PHP-тернарный оператор против оператора нулевой коалесценции

Может ли кто-нибудь объяснить различия между сокращением тернарных операторов ( ?: 🙂 И нулевым коалесцирующим оператором ( ?? ) в PHP?

Когда они ведут себя по-разному и когда одинаково (если это вообще происходит)?

 $a ?: $b 

VS.

 $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'; 

Теперь это правильный коалесцирующий оператор.

Основное различие заключается в том, что

  1. Терминальное выражение оператора expr1 ?: expr3 возвращает expr1 если expr1 значение TRUE но, с другой стороны, выражение Null Coalescing Operator (expr1) ?? (expr2) (expr1) ?? (expr2) вычисляет expr1 если expr1 не является NULL

  2. Терминальный оператор expr1 ?: expr3 испускает уведомление, если значение левой стороны (expr1) не существует, но, с другой стороны, Null Coalescing Operator (expr1) ?? (expr2) (expr1) ?? (expr2) В частности, не выделяет уведомление, если значение левой стороны (expr1) не существует, как isset() .

  3. ТернарОператор оставлен ассоциативным

     ((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. Операторы стекирования …

  1. Тернарный оператор может быть уложен в стопку

     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 {} 
  2. Оператор Null Coalese может быть уложен

     $v = $x ?? $y ?? $z; 

    Это последовательность:

     if(!isset($x) || is_null($x) ) {} else if(!isset($y) || is_null($y) ) {} else {} 
  3. Используя укладку, я могу сократить это:

     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

Interesting Posts

Как связать несколько значений с одним текстовым блоком WPF?

Как загрузить ресурс из каталога WEB-INF веб-архива

Как разрешить Chrome (браузеру) загружать небезопасный контент?

Привязать приложение к определенному сетевому интерфейсу

Где Windows 8 хранит мини-накачки пользовательского режима?

Тестирование stream.good () или! Stream.eof () дважды читает последнюю строку

Какова цель неявного типа авторизации гранта в OAuth 2?

Webkit CSS для управления полем вокруг цвета во вводе ?

Конфигурация com.sun.faces.config.ConfigureListener

Инициализация нескольких переменных для одного и того же значения в Java

поддержка FragmentPagerAdapter содержит ссылку на старые fragmentы

Есть ли декомпилятор Visual Basic 6?

Есть ли способ переопределить переменные classа в Java?

Как заполнить выпадающий список json-данными в jquery?

Есть ли формат файла Windows с <CR> -сепаратированными записями (без символов <LF>)?

Давайте будем гением компьютера.