PHP тернарный оператор против нулевого коалесцирующего оператора
может ли кто-нибудь объяснить различия между стенографией троичного оператора (?:
) и нуль-коалесцирующий оператор (??
) в PHP?
когда они ведут себя по-разному и когда одинаково (если это вообще происходит)?
$a ?: $b
VS.
$a ?? $b
9 ответов
когда ваш первый аргумент равен null, они в основном одинаковы, за исключением того, что объединение null не приведет к E_NOTICE
когда у вас есть неопределенная переменная. The PHP 7.0 миграционные документы говорит:
оператор коалесцирования null (??) был добавлен как синтаксический сахар для общего случая необходимости использования Троицы в сочетании с isset (). Он возвращает свой первый операнд, если он существует и не равен NULL; в противном случае он возвращает его второй операнд.
вот пример кода, чтобы продемонстрировать это:
<?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';
отметим, что это не проверяет правдивость. Оно проверяет только если оно установлено и не ноль.
вы также можете сделать это, и первый определена (установите, а не null
) будет возвращено значение:
$val = $input1 ?? $input2 ?? $input3 ?? 'default';
теперь это правильный оператор объединения.
главное отличие в том, что
Тернарный Оператор выражение
expr1 ?: expr3
возвращаетexpr1
еслиexpr1
значениеTRUE
но с другой стороны Оператор Объединения Null выражение(expr1) ?? (expr2)
значениеexpr1
еслиexpr1
is неNULL
троичная Оператор
expr1 ?: expr3
испустите извещение если левая сторона значение(expr1)
не существует, но с другой стороны!--26-->Оператор Объединения 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);
Вот таблица, которая объясняет разницу и сходство между '??'
и ?:
специальное примечание: нулевой коалесцирующий оператор и тернарный оператор выражение, и что оно не вычисляется для переменной, а для результат выражения. Это важно знать, если вы хотите возвращает переменную по ссылке. Заявление возвращает $foo ?? $бар и вернуть $var = = 42 ? $a : $b; в функции возврата по ссылке будет поэтому не работает и выдается предупреждение.
оба они ведут себя по-разному, когда дело доходит до динамической обработки данных.
Если переменная пуста ( " ), нулевое объединение будет рассматривать переменную как 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 только через. - и он всегда возвращает первый параметр, если первый параметр бывает
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()
Регистрация - e.g проверьте, существует ли объект -
$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, если предыдущий аргумент равен null. С ??
про то, что нет E_NOTICE, но то, что он не оценивает 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: ---
однако, развивая тернарный оператор, мы можем заставить ложную или пустую строку "" вести себя так, как если бы она была нулем, не бросая 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