РНР тернарный оператор против нуль-коалесцирующий оператора
может ли кто-нибудь объяснить различия между стенографией тернарного оператора (?:
) и оператор коалесценции 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
через - включаяNULL
0
,empty string
,NULL
,false
,!isset()
,empty()
.. все, что пахнет фальшиво- так же, как классический тернарный оператор:
echo ($x ? $x : false)
- Примечание:
?:
броситPHP NOTICE
on undefined (unset
или!isset()
) переменные3. Итак, доктор, когда я использую
??
и?:
..
- я только шучу - я не врач и это всего лишь интерпретация
- я хотел бы использовать
?:
когда
- делаешь
empty($x)
проверки- классическая троичная операция, как
!empty($x) ? $x : $y
можно сократить до$x ?: $y
if(!$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