Ответы:
Когда ваш первый аргумент равен нулю, они в основном совпадают, за исключением того, что объединение с нулем не будет выводить, E_NOTICE
когда у вас есть неопределенная переменная. Документация по миграции на PHP 7.0 имеет следующее:
Нулевой оператор объединения (??) был добавлен в качестве синтаксического сахара для общего случая необходимости использования троичного в сочетании с isset (). Он возвращает свой первый операнд, если он существует и не равен NULL; в противном случае он возвращает свой второй операнд.
Вот пример кода, чтобы продемонстрировать это:
<?php
$a = null;
print $a ?? 'b'; // b
print "\n";
print $a ?: 'b'; // b
print "\n";
print $c ?? 'a'; // a
print "\n";
print $c ?: 'a'; // Notice: Undefined variable: c in /in/apAIb on line 14
print "\n";
$b = array('a' => null);
print $b['a'] ?? 'd'; // d
print "\n";
print $b['a'] ?: 'd'; // d
print "\n";
print $b['c'] ?? 'e'; // e
print "\n";
print $b['c'] ?: 'e'; // Notice: Undefined index: c in /in/apAIb on line 33
print "\n";
Линии, которые имеют уведомление, - это те, где я использую сокращенный тернарный оператор, а не оператор объединения нулей. Тем не менее, даже с уведомлением, PHP даст тот же ответ обратно.
Выполните код: https://3v4l.org/McavC
Конечно, это всегда предполагает первый аргумент null
. Как только он перестанет иметь значение null, вы получите различия в том, что ??
оператор всегда будет возвращать первый аргумент, тогда как ?:
сокращение будет только в том случае, если первый аргумент верен, и это зависит от того, как PHP будет приводить типы к булевому значению .
Так:
$a = false ?? 'f'; // false
$b = false ?: 'g'; // 'g'
тогда $a
будет равно false
и $b
равно 'g'
.
$b = []; var_dump($b['a']['b']['c'] ?? 'default');
или с объектами$b = new Foo; var_dump($b->a()->b()->c() ?? 'default');
$a = [];
. См .: 3v4l.org/iCCa0
Запустил ниже на 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"
??
:??
это как "ворота", которые пропускают только NULL .NULL
. ??
же, как( !isset() || is_null() )
?:
?:
это как ворота, которые пропускают anything falsy
- в том числеNULL
0
, empty string
, NULL
, false
, !isset()
, empty()
.. все , что пахнет falsyecho ($x ? $x : false)
?:
будет выбрасывать PHP NOTICE
неопределенные ( unset
или !isset()
) переменные??
и ?:
..?:
когда
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();
Тройной Оператор может быть сложен ...
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($user_name){
$name = $user_name;
}else {
$name = 'anonymous';
}
} else {
$name = $_GET['name'];
}
К этому:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
Круто, верно? :-)
Если вы используете ярлык тернарный оператор, как это, это вызовет уведомление, если $_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 Коалесцентного Оператором выражение (expr1) ?? (expr2)
принимает значение , expr1
если expr1
является не NULL
Тернарный оператор expr1 ?: expr3
выдает уведомление, если левое значение (expr1)
не существует, но, с другой стороны, Null Coalescing Operator (expr1) ?? (expr2)
В частности, не выдает уведомление, если левое значение (expr1)
не существует, как, например isset()
.
TernaryOperator остается ассоциативным
((true ? 'true' : false) ? 't' : 'f');
Нулевой оператор слияния является ассоциативным справа
($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);
Нулевой оператор объединения (??)
$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
It returns its first operand if it exists and is not NULL; otherwise it returns its second operand
.
Оба являются сокращениями для более длинных выражений.
?:
это сокращение от $a ? $a : $b
. Это выражение будет иметь значение $ a, если $ a равно TRUE .
??
это сокращение от isset($a) ? $a : $b
. Это выражение будет иметь значение $ a, если $ a установлено и не равно нулю.
Их варианты использования перекрываются, когда $ a не определено или равно нулю. Если $ a ??
не определено, E_NOTICE не будет получен, но результаты будут такими же. Когда $ a равно нулю, результат тот же.
Для начинающих:
Нулевой оператор объединения (??)
Все верно, кроме null
значений и неопределенных (переменная / индекс массива / атрибуты объекта)
например:
$array = [];
$object = new stdClass();
var_export (false ?? 'second'); # false
var_export (true ?? 'second'); # true
var_export (null ?? 'second'); # 'second'
var_export ('' ?? 'second'); # ""
var_export ('some text' ?? 'second'); # "some text"
var_export (0 ?? 'second'); # 0
var_export ($undefinedVarible ?? 'second'); # "second"
var_export ($array['undefined_index'] ?? 'second'); # "second"
var_export ($object->undefinedAttribute ?? 'second'); # "second"
это в основном проверка, что переменная (индекс массива, атрибут объекта и т. д.) существует, а не существует null
. похоже на isset
функцию
Сокращенное обозначение троичного оператора (? :)
каждые ложные вещи ( false
, null
, 0
, пустая строка) пришли как ложные, но если это не определено также приходят как ложные , но Notice
выбросит
бывший
$array = [];
$object = new stdClass();
var_export (false ?: 'second'); # "second"
var_export (true ?: 'second'); # true
var_export (null ?: 'second'); # "second"
var_export ('' ?: 'second'); # "second"
var_export ('some text' ?? 'second'); # "some text"
var_export (0 ?: 'second'); # "second"
var_export ($undefinedVarible ?: 'second'); # "second" Notice: Undefined variable: ..
var_export ($array['undefined_index'] ?: 'second'); # "second" Notice: Undefined index: ..
var_export ($object->undefinedAttribute ?: 'second'); # "Notice: Undefined index: ..
Надеюсь это поможет
Прокрутите вниз по этой ссылке и просмотрите раздел, он дает вам сравнительный пример, как показано ниже:
<?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';
?>
Однако не рекомендуется объединять операторы в цепочку, так как это усложняет понимание кода при последующем его чтении.
Нулевой оператор объединения (??) был добавлен в качестве синтаксического сахара для общего случая необходимости использования троичного в сочетании с isset (). Он возвращает свой первый операнд, если он существует и не равен NULL; в противном случае он возвращает свой второй операнд.
По сути, использование оператора объединения делает его автоматической проверкой на нуль в отличие от троичного оператора.
a || b || c
шаблон в JS, за исключением того, что PHP можно использовать для логических значений ( false || 2
в JS - 2; false ?? 2
в PHP - false)
Другие ответы идут глубоко и дают большие объяснения. Для тех, кто ищет быстрый ответ,
$a ?: 'fallback'
является $a ? $a : 'fallback'
пока
$a ?? 'fallback'
является $a = isset($a) ? $a : 'fallback'
Основное отличие будет в том случае, если левый оператор либо:
0
, ''
, false
, []
, ...)$a =
в приведенном выше расширении ??
. $a ?? 'fallback'
не устанавливает и не изменяет значение $ a. (Он просто возвращает значение).
Кажется , есть свои плюсы и минусы использования либо ??
или ?:
. Преимущество использования ?:
состоит в том, что он оценивает false и null и "" то же самое. Дело в том, что он сообщает E_NOTICE, если предыдущий аргумент равен нулю. С ??
профи, что нет E_NOTICE, но мошенник в том , что она не оценивает ложные и нуль то же самое. Исходя из моего опыта, я видел, как люди начинают взаимозаменяемо использовать 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---
Лично я думаю, что было бы очень хорошо, если бы будущая версия PHP включала еще один новый оператор: он :?
заменил приведенный выше синтаксис. то есть:
// $var = $false :? "true";
тот синтаксис будет оценивать нуль, ложь и "" одинаково и не выбрасывать E_NOTICE ...
?? null ?:
вещь довольно крутая, спасибо, мистер. умный парень
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
isset($_POST['fullname'])
уже проверяет NULL
значения - так что && !is_null($_POST['fullname'])
в первом примере все равно избыточно
При использовании суперглобальных объектов, таких как $ _GET или $ _REQUEST, вы должны знать, что они могут быть пустой строкой. В этом конкретном случае этот пример
$username = $_GET['user'] ?? 'nobody';
потерпит неудачу, потому что значение $ username теперь является пустой строкой.
Поэтому при использовании $ _GET или даже $ _REQUEST вы должны использовать вместо этого троичный оператор, например:
$username = (!empty($_GET['user'])?$_GET['user']:'nobody';
Теперь значение $ username равно «nobody», как и ожидалось.