РНР тернарный оператор против нуль-коалесцирующий оператора
может ли кто-нибудь объяснить различия между стенографией тернарного оператора (?:) и оператор коалесценции null (??) в PHP?
когда они ведут себя по-разному и когда одинаково (если это вообще происходит)?
$a ?: $b
VS.
$a ?? $b
9 ответов:
когда ваш первый аргумент равен null, они в основном одинаковы, за исключением того, что Коалесценция null не выводит
E_NOTICEкогда у вас есть неопределенная переменная. Элемент PHP 7.0 migration docs говорит:оператор коалесценции null (??) был добавлен в качестве синтаксического сахара для общего случая необходимости использовать троичный в сочетании с isset () и. Он возвращает свой первый операнд, если он существует и не является нулевым; в противном случае он возвращает его второй операнд.
вот пример кода, чтобы продемонстрировать это:
<?php $a = null; print $a ?? 'b'; print "\n"; print $a ?: 'b'; print "\n"; print $c ?? 'a'; print "\n"; print $c ?: 'a'; print "\n"; $b = array('a' => 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строки, в которых есть уведомление, - это те, где я использую стенографический тернарный оператор, а не оператор слияния null. Однако, даже с уведомлением, PHP даст тот же ответ обратно.
выполнить код:https://3v4l.org/McavC
конечно, это всегда предполагая, что первый аргумент
null. Как только это больше не null, то вы в конечном итоге с различиями в том, что??оператор всегда возвращает первый аргумент, в то время как?:стенография была бы только в том случае, если бы первый аргумент был правдивым, и это зависит от того, как PHP будет вводить-cast вещи в логическое.так:
$a = false ?? 'f'; $b = false ?: 'g';было бы тогда
$aбудет равнаfalseи$bравна'g'.
если вы используете ярлык тернарного оператора, как это, это вызовет уведомление, если
$_GET['username']не установлено:$val = $_GET['username'] ?: 'default';так что вместо этого вы должны сделать что-то вроде этого:
$val = isset($_GET['username']) ? $_GET['username'] : 'default';The оператор коалесценции null эквивалентно приведенному выше утверждению и вернет 'default', если
$_GET['username']не установлен или составляетnull:$val = $_GET['username'] ?? 'default';отметим, что он не проверяет truthiness. Он проверяет только если он установлен и не ноль.
вы также можете сделать это, и первый определена (установите, а не
null) значение будет возвращено:$val = $input1 ?? $input2 ?? $input3 ?? 'default';теперь это правильный коалесцирующий оператор.
главное отличие в том, что
Тернарный Оператор выражение
expr1 ?: expr3возвращаетexpr1еслиexpr1значениеTRUEно с другой стороны Оператор Коалесценции Null выражение(expr1) ?? (expr2)оценивает вexpr1еслиexpr1и неNULLтроичная Оператор
expr1 ?: expr3выдать уведомление, если левая сторона значение(expr1)не существует, но с другой стороны Оператор Коалесценции Null(expr1) ?? (expr2)в частности, не выдает уведомление, если значение левой стороны(expr1)тут не существует, какisset().TernaryOperator остается ассоциативным
((true ? 'true' : false) ? 't' : 'f');Оператор Коалесценции Null правильно ассоциативно
($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);Оператор Коалесценции Null
(??)$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);Вот таблица, которая объясняет разницу и сходство между
'??'и?:специальное примечание: нулевой коалесцирующий оператор и тернарный оператор является выражение, и что оно не вычисляется для переменной, а для результат выражения. Это важно знать, если вы хотите возвращает переменную по ссылке. Заявление о возврате $фу ?? $бар и вернуть $var = = 42 ? $a: $b; в функции возврата по ссылке будет поэтому не работает и выдается предупреждение.
оба они ведут себя по-разному, когда дело доходит до динамической обработки данных.
Если переменная пуста ( " ), Коалесценция null будет рассматривать переменную как true, но стенографический тернарный оператор не будет. и это то, что нужно иметь в виду.
$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 (
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 через.- и он всегда возвращает первый параметр, если первый параметр оказывается
NULL.- это значит
??такой же, как( !isset() || is_null() )2. Тернарный Оператор -
?:
?:это как ворота, которые позволяютanything falsyчерез - включаяNULL0,empty string,NULL,false,!isset(),empty().. все, что пахнет фальшиво- так же, как классический тернарный оператор:
echo ($x ? $x : false)- Примечание:
?:броситPHP NOTICEon undefined (unsetили!isset()) переменные3. Итак, доктор, когда я использую
??и?:..
- я только шучу - я не врач и это всего лишь интерпретация
- я хотел бы использовать
?:когда
- делаешь
empty($x)проверки- классическая троичная операция, как
!empty($x) ? $x : $yможно сократить до$x ?: $yif(!$x) { fn($x); } else { fn($y); }может укоротить доfn(($x ?: $y))- я хотел бы использовать
??когда
- я хочу
!isset() || is_null()Регистрация- например, проверьте, существует ли объект -
$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 {}нулевой оператор 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';круто, да? : -)
прокрутите вниз на этой ссылка и просмотр раздела, это дает вам сравнительный пример, как показано ниже:
<?php /** Fetches the value of $_GET['user'] and returns 'nobody' if it does not exist. **/ $username = $_GET['user'] ?? 'nobody'; /** This is equivalent to: **/ $username = isset($_GET['user']) ? $_GET['user'] : 'nobody'; /** Coalescing can be chained: this will return the first defined value out of $_GET['user'], $_POST['user'], and 'nobody'. **/ $username = $_GET['user'] ?? $_POST['user'] ?? 'nobody'; ?>однако не рекомендуется связывать операторы, так как это затрудняет понимание кода при его последующем чтении.
оператор коалесценции null (??) был добавлен в качестве синтаксического сахара для общего случая необходимости использования тернарного в сочетании с isset (). Он возвращает первый операнд, если он существует и не NULL; в противном случае он возвращает свой второй операнд.
по существу, использование коалесцирующего оператора сделает его автоматической проверкой на null в отличие от тернарного оператора.
кажется, есть плюсы и минусы в использовании либо
??или?:. Про использование?:это то, что он оценивает false и null и "" то же самое. Con заключается в том, что он сообщает E_NOTICE, если предыдущий аргумент равен нулю. С??pro заключается в том, что нет E_NOTICE, но con заключается в том, что он не оценивает false и null одинаково. По моему опыту, я видел, как люди начинают использовать null и false взаимозаменяемо, но затем они в конечном итоге прибегают к изменению своего кода, чтобы быть согласуется с использованием либо null, либо false, но не обоих. Альтернативой является создание более сложного троичного условия:(isset($something) or !$something) ? $something : $something_else.ниже приведен пример разницы в использовании
??оператор, использующий как null, так и false:$false = null; $var = $false ?? "true"; echo $var . "---<br>";//returns: true--- $false = false; $var = $false ?? "true"; echo $var . "---<br>"; //returns: ---однако, развивая тернарный оператор, мы можем заставить ложную или пустую строку "" вести себя так, как если бы это было null, не бросая e_notice:
$false = null; $var = (isset($false) or !$false) ? $false : "true"; echo $var . "---<br>";//returns: --- $false = false; $var = (isset($false) or !$false) ? $false : "true"; echo $var . "---<br>";//returns: --- $false = ""; $var = (isset($false) or !$false) ? $false : "true"; echo $var . "---<br>";//returns: --- $false = true; $var = (isset($false) or !$false) ? $false : "true"; echo $var . "---<br>";//returns: 1---лично я думаю, что это было бы действительно приятно, если будущий rev PHP включил еще один новый оператор:
:?это заменило приведенный выше синтаксис. то есть:// $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. Взгляните на следующий пример:<?php # case 1: $greeting = 'Hola'; echo $greeting ?? 'Hi There'; # outputs: 'Hola' # case 2: $greeting = null; echo $greeting ?? 'Hi There'; # outputs: 'Hi There' # case 3: unset($greeting); echo $greeting ?? 'Hi There'; # outputs: 'Hi There'в приведенном выше примере кода указано, что
Null Coalescing operatorобрабатывает несуществующую переменную и переменную, которая имеет значениеNULLточно так же.
Null Coalescing operator- это улучшение по сравнению сternary operator. Посмотрите на следующий фрагмент кода, сравнивая два:<?php /* example: checking for the $_POST field that goes by the name of 'fullname'*/ # in ternary operator echo "Welcome ", (isset($_POST['fullname']) && !is_null($_POST['fullname']) ? $_POST['fullname'] : 'Mr. Whosoever.'); # outputs: Welcome Mr. Whosoever. # in null coalecing operator echo "Welcome ", ($_POST['fullname'] ?? 'Mr. Whosoever.'); # outputs: Welcome Mr. Whosoever.Итак, разница между ними заключается в том, что
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
