Відповіді:
Коли ваш перший аргумент є недійсним, вони в основному однакові, за винятком того, що злиття нуля не виведе a, 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
. Як тільки це більше не буде нульовим, тоді ви закінчуєтесь відмінностями в тому, що ??
оператор завжди повертає перший аргумент під час?:
стенограма буде тільки в тому випадку, якщо перший аргумент є правдоподібним, і це спирається на те, як 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();
Ternary Operator можна скласти ...
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 {}
Null Coalese Operator можна скласти ...
$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 Коалесцентного оператором (expr1) ?? (expr2)
Зокрема, не виділяє повідомлення , якщо сторона значення лівого (expr1)
не існує, так само , як isset()
.
TernaryOperator залишається асоціативним
((true ? 'true' : false) ? 't' : 'f');
Null Coalescing Operator є правильним асоціативом
($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 Coalescing Operator (??)
$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);
Ось таблиця, яка пояснює різницю та подібність між '??'
і?:
Спеціальна примітка: оператор з’єднання нуля та потрійний оператор - це вираз, і він оцінює не змінну, а результат виразу. Це важливо знати, чи потрібно повернути змінну за посиланням. Виписка return $ foo ?? $ бар; і повернути $ var == 42? $ a: $ b; в тому, що функція зворотного посилання не працює, і попередження видається.
Обидва вони поводяться по-різному, якщо мова йде про динамічну обробку даних.
Якщо змінна порожня (''), нульове злиття вважатиме цю змінну справжньою, але короткочасний потрійний оператор не буде. І це є на увазі.
$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 оцінюється як ІСТИНА .
??
короткий для 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 - помилково)
Інші відповіді заглиблюються і дають чудові пояснення. Для тих, хто шукає швидкої відповіді,
$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, але не обидва. Альтернативою є створення більш детальної потрійної умови:(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";
Цей синтаксис оцінюватиме "null", "false" і "" однаково, а не кидатиме 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';
не вдасться, оскільки значення $ ім'я користувача зараз є порожнім рядком.
Тож, використовуючи $ _GET або навіть $ _REQUEST, вам слід скористатись потрійним оператором замість цього:
$username = (!empty($_GET['user'])?$_GET['user']:'nobody';
Тепер значення $ ім'я користувача - "ніхто", як очікувалося.