wake-up-neo.com

PHP ternärer Operator vs. nuller Koaleszenzoperator

Kann jemand die Unterschiede zwischen dem ternären Operator-Kürzel (?:) und dem Nullkoaleszenzoperator (??) in PHP erklären?

Wann verhalten sie sich anders und wann (wenn das überhaupt passiert)?

$a ?: $b

VS.

$a ?? $b
205
balping

Wenn Ihr erstes Argument null ist, sind sie im Grunde genommen gleich, mit der Ausnahme, dass beim Nullzusammenführen kein E_NOTICE Ausgegeben wird, wenn Sie eine undefinierte Variable haben. Das PHP 7.0 Migrationsdokumente hat folgendes zu sagen:

Der Null-Koaleszenzoperator (??) wurde als syntaktischer Zucker für den allgemeinen Fall hinzugefügt, dass ein Ternär in Verbindung mit isset () verwendet werden muss. Es gibt seinen ersten Operanden zurück, wenn er existiert und nicht NULL ist. Andernfalls wird der zweite Operand zurückgegeben.

Hier ist ein Beispielcode, um dies zu demonstrieren:

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

In den Zeilen mit dem Hinweis verwende ich den ternären Kurzoperator und nicht den Nullkoaleszenzoperator. Trotz der Benachrichtigung gibt PHP die gleiche Antwort zurück.

Führen Sie den Code aus: https://3v4l.org/McavC

Dies setzt natürlich immer voraus, dass das erste Argument null ist. Sobald es nicht mehr null ist, kommt es zu Unterschieden darin, dass der Operator ?? Immer das erste Argument zurückgibt, während die Abkürzung ?: Nur dann, wenn das erste Argument wahr ist und sich darauf stützt wie PHP würde Dinge in einen Booleschen Wert umwandeln .

Damit:

$a = false ?? 'f'; // false
$b = false ?: 'g'; // 'g'

wäre dann $a gleich false und $b gleich 'g'.

267
MasterOdin

Wenn Sie den ternären Verknüpfungsoperator wie folgt verwenden, wird eine Benachrichtigung angezeigt, wenn $_GET['username'] nicht festgelegt ist:

$val = $_GET['username'] ?: 'default';

Stattdessen musst du so etwas tun:

$val = isset($_GET['username']) ? $_GET['username'] : 'default';

Der null-Coalescing-Operator entspricht der obigen Anweisung und gibt 'default' zurück, wenn $_GET['username'] nicht festgelegt ist oder null:

$val = $_GET['username'] ?? 'default';

Beachten Sie, dass die Wahrhaftigkeit nicht überprüft wird . Es wird nur geprüft, ob es gesetzt ist und nicht null.

Sie können dies auch tun und der erste definierte (set und nicht null) -Wert wird zurückgegeben:

$val = $input1 ?? $input2 ?? $input3 ?? 'default';

Das ist jetzt ein richtiger Koaleszenzoperator.

57
Andrew

Der Hauptunterschied ist der

  1. Ternärer Operator Ausdruck expr1 ?: expr3 Gibt expr1 Zurück, wenn expr1 Zu TRUE ausgewertet wird, andererseits Null Koaleszenzoperator Ausdruck (expr1) ?? (expr2) Ergibt expr1, Wenn expr1 nichtNULL ist

  2. Ternärer Operatorexpr1 ?: expr3 Gibt einen Hinweis aus, wenn der Wert auf der linken Seite (expr1) Nicht existiert, aber auf der anderen Seite Null Coalescing Operator(expr1) ?? (expr2) Gibt insbesondere dann keinen Hinweis aus, wenn der Wert auf der linken Seite (expr1) Nicht existiert, genau wie isset().

  3. TernaryOperator bleibt assoziativ

    ((true ? 'true' : false) ? 't' : 'f');
    

    Null Coalescing Operator ist richtig assoziativ

    ($a ?? ($b ?? $c));
    

Lassen Sie uns nun den Unterschied zwischen durch Beispiel erklären:

Ternärer Operator(?:)

$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);

Hier ist die Tabelle, die den Unterschied und die Ähnlichkeit zwischen '??' Und ?: Erklärt.

enter image description here

Besonderer Hinweis: Der null-Koaleszenzoperator und der ternäre Operator sind Ausdrücke, die nicht als Variable, sondern als Ergebnis eines Ausdrucks ausgewertet werden. Dies ist wichtig zu wissen, wenn Sie eine Variable als Referenz zurückgeben möchten. Die Anweisung return $ foo ?? $ bar; und $ var == 42 zurückgeben? $ a: $ b; Bei einer Return-by-Reference-Funktion wird daher nicht gearbeitet und eine Warnung ausgegeben.

40
Dhairya Lakhera

Laufen Sie unten auf den interaktiven PHP-Modus (php -a am Terminal). Der Kommentar in jeder Zeile zeigt das Ergebnis.

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"

Das ist meine Interpretation:

1. Der Nullkoaleszenzoperator - ??:

  • ?? ist wie ein "Gate", das nur NULL durch durchlässt. 
  • Also es gibt immer den ersten Parameter zurück, es sei denn der erste Parameter ist NULL
  • Dies bedeutet, dass ?? mit ( !isset() || is_null() ) identisch ist.

2. Der ternäre Operator - ?:

  • ?: IST WIE EIN TOR, DAS anything falsy DURCHL&AUML;SST - EINSCHLIE&SZLIG;LICH NULL
  • 0, empty string, NULL, false, !isset(), empty() .. alles was falsch riecht 
  • Genau wie der klassische ternäre Operator: echo ($x ? $x : false) 
  • HINWEIS: ?: wirft PHP NOTICE für undefined (unset oder !isset()) Variablen ab

3. Also, Doktor, wann verwende ich ?? und ?: ..

  • Ich scherze nur - ich bin kein Arzt und das ist nur eine Interpretation 
  • Ich würde ?: verwenden, wenn
    • empty($x)-Prüfungen durchführen
    • Der klassische ternäre Betrieb wie !empty($x) ? $x : $y kann zu $x ?: $y verkürzt werden. 
    • if(!$x) { fn($x); } else { fn($y); } kann zu fn(($x ?: $y)) verkürzt werden 
  • Ich würde ?? verwenden, wenn
    • Ich möchte eine !isset() || is_null()-Prüfung durchführen 
    • Überprüfen Sie beispielsweise, ob ein Objekt vorhanden ist - $object = $object ?? new objClassName();

4. Stapeloperatoren ...

  1. Ternary Operator kann gestapelt werden ... 

    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
    

    Quelle und Kredit für diesen Code

    Dies ist im Grunde eine Folge von:

    if( truthy ) {}
    else if(truthy ) {}
    else if(truthy ) {}
    ..
    else {}
    
  2. Null Coalese Operator kann gestapelt werden ... 

    $v = $x ?? $y ?? $z; 
    

    Dies ist eine Sequenz von:

    if(!isset($x) || is_null($x) ) {} 
    else if(!isset($y) || is_null($y) ) {}
    else {}
    
  3. Mit Stacking kann ich das abkürzen:

    if(!isset($_GET['name'])){
       if(isset($user_name) && !empty($user_name)){
          $name = $user_name;
       }else {
          $name = 'anonymous';
       }
    } else { 
       $name = $_GET['name'];
    }
    

    Dazu:

    $name = $_GET['name'] ?? $user_name ?: 'anonymous';
    

    Cool, richtig? :-)

27
a20

Beide verhalten sich im dynamischen Umgang mit Daten unterschiedlich.

Wenn die Variable leer ist (''), wird das Null-Koaleszieren die Variable als wahr behandeln, der ternäre Kurzschriftoperator jedoch nicht. Und das ist etwas zu bedenken.

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

Und die Ausgabe:

1b
2b

2d
1f

Notice: Undefined variable: e in /in/ZBAa1 on line 21
2f

Link: https://3v4l.org/ZBAa1

12
Chazy Chaz

Beide sind Abkürzungen für längere Ausdrücke.

?: steht für $a ? $a : $b. Dieser Ausdruck wird in $ a ausgewertet, wenn $ a inTRUEausgewertet wird.

?? steht für isset($a) ? $a : $b. Dieser Ausdruck wird zu $ ​​a ausgewertet, wenn $ a gesetzt ist und nicht null.

Ihre Anwendungsfälle überschneiden sich, wenn $ a undefined oder null ist. Wenn $ a nicht definiert ist, erzeugt ?? kein E_NOTICE, die Ergebnisse sind jedoch gleich. Wenn $ a null ist, ist das Ergebnis dasselbe.

7
Dean Or

Für die Anfänger:

Nullkoaleszenzoperator (??)

Alles ist wahr außer null Werten und undefiniert (Variablen/Array-Index/Objektattribute)

ex:

$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"

dies ist im Grunde genommen eine Überprüfung, ob die Variable (Array-Index, Objektattribut usw.) existiert und nicht null. ähnlich der Funktion isset

Kurzform des ternären Operators (?:)

alle falschen Dinge (false, null, 0, leere Zeichenfolge) werden als falsch gewertet, aber wenn es nicht definiert ist, wird es auch als falsch gewertet, aber Notice

ex

$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: ..

Hoffe das hilft

4
Supun Praneeth

Scrollen Sie nach unten auf this link und sehen Sie sich den Abschnitt an. Hier sehen Sie ein Vergleichsbeispiel wie unten:

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

Es wird jedoch nicht empfohlen, die Operatoren zu verketten, da dies das Verständnis des Codes beim späteren Lesen erschwert.

Der nullkoaleszierende Operator (??) wurde als syntaktischer Zucker hinzugefügt, wenn häufig ein Ternär in Verbindung mit isset () verwendet werden muss. Es gibt den ersten Operanden zurück, wenn er existiert und nicht NULL ist. Andernfalls wird der zweite Operand zurückgegeben.

Im Wesentlichen wird der Koaleszenzoperator im Gegensatz zum ternären Operator automatisch auf Null überprüft.

3
Script47

Anscheinend gibt es Vor- und Nachteile, entweder ?? oder ?: zu verwenden. Der Vorteil von ?: ist, dass "" false und null und "" dasselbe ausgewertet werden. Der Nachteil ist, dass ein E_NOTICE gemeldet wird, wenn das vorhergehende Argument NULL ist. Mit ?? ist der Pro, dass es kein E_NOTICE gibt, aber der Nachteil ist, dass es nicht false und null gleich auswertet. In meiner Erfahrung habe ich gesehen, dass die Menschen anfangen, Null und Falsch austauschbar zu verwenden, aber schließlich haben sie sich dazu entschieden, ihren Code zu ändern, um entweder Null oder Falsch zu verwenden, aber nicht beides. Eine Alternative besteht darin, eine kompliziertere ternäre Bedingung zu erstellen: (isset($something) or !$something) ? $something : $something_else.

Im Folgenden finden Sie ein Beispiel für den Unterschied bei der Verwendung des ??-Operators, wobei sowohl null als auch falsch verwendet werden: 

$false = null;
$var = $false ?? "true";
echo $var . "---<br>";//returns: true---

$false = false;
$var = $false ?? "true";
echo $var . "---<br>"; //returns: ---

Indem wir den ternären Operator näher erläutern, können wir eine "" falsche oder leere Zeichenfolge "" so verhalten, als wäre sie eine Null, ohne einen e_notice zu werfen:

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

Ich persönlich denke, es wäre wirklich schön, wenn eine zukünftige Version von PHP einen weiteren neuen Operator enthält: :?, der die obige Syntax ersetzt. ie: // $var = $false :? "true"; Diese Syntax würde null, falsch und "" gleichermaßen auswerten und keine E_NOTICE werfen ...

3
Damian Green

Die anderen Antworten gehen tief und geben großartige Erklärungen. Für diejenigen, die eine schnelle Antwort suchen,

$a ?: 'fallback' ist $a ? $a : 'fallback'

während

$a ?? 'fallback' ist $a = isset($a) ? $a : 'fallback'


Der Hauptunterschied wäre, wenn der linke Operator entweder:

  • Ein falscher Wert, der NICHT null ist (0, '', false, [], ...)
  • Eine undefinierte Variable
1
Yaron U.
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.
1
Čamo

Null Coalescing operator führt nur zwei Aufgaben aus: Es überprüft whether the variable is set und whether it is null. Schauen Sie sich das folgende Beispiel an:

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

Das obige Codebeispiel besagt, dass Null Coalescing operator eine nicht vorhandene Variable und eine Variable, die auf NULL gesetzt ist, auf dieselbe Weise behandelt.

Null Coalescing operator ist eine Verbesserung gegenüber ternary operator. Schauen Sie sich das folgende Code-Snippet an, das die beiden vergleicht:

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

Der Unterschied zwischen den beiden besteht also darin, dass der Null Coalescing operator-Operator dazu entwickelt wurde, undefinierte Variablen besser zu handhaben als der ternary operator. Während ternary operator eine Abkürzung für if-else ist.

Null Coalescing operator soll ternary operator nicht ersetzen, aber in einigen Anwendungsfällen wie im obigen Beispiel können Sie sauberen Code mit weniger Aufwand schreiben.

Credits: http://dwellupper.io/post/6/php7-null-coalescing-operator-usage-and-examples

0
Pranav Rana

Wenn Sie Superglobale wie $ _GET oder $ _REQUEST verwenden, sollten Sie wissen, dass es sich um einen leeren String handeln kann

$username = $_GET['user'] ?? 'nobody';

schlägt fehl, da der Wert von $ username jetzt eine leere Zeichenfolge ist.

Wenn Sie also $ _GET oder sogar $ _REQUEST verwenden, sollten Sie stattdessen den ternären Operator verwenden:

$username = (!empty($_GET['user'])?$_GET['user']:'nobody';

Jetzt ist der Wert von $ username wie erwartet "nobody".

0