РНР тернарный оператор против нуль-коалесцирующий оператора


может ли кто-нибудь объяснить различия между стенографией тернарного оператора (?:) и оператор коалесценции null (??) в PHP?

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

$a ?: $b

VS.

$a ?? $b
9 164

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

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

главное отличие в том, что

  1. Тернарный Оператор выражение expr1 ?: expr3 возвращает expr1 если expr1 значение TRUE но с другой стороны Оператор Коалесценции Null выражение (expr1) ?? (expr2) оценивает в expr1 если expr1 и неNULL

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

  3. 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);

Вот таблица, которая объясняет разницу и сходство между '??' и ?:

enter image description here

специальное примечание: нулевой коалесцирующий оператор и тернарный оператор является выражение, и что оно не вычисляется для переменной, а для результат выражения. Это важно знать, если вы хотите возвращает переменную по ссылке. Заявление о возврате $фу ?? $бар и вернуть $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. Операторы суммирования ...

  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. нулевой оператор 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';
    

    круто, да? : -)

прокрутите вниз на этой ссылка и просмотр раздела, это дает вам сравнительный пример, как показано ниже:

<?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