Quelqu'un peut-il expliquer les différences entre l'opérateur abrégé de l'opérateur ternaire (?:
) et l'opérateur de fusion nul (??
) en PHP?
Quand se comportent-ils différemment et quand de la même manière (si cela se produit même)?
$a ?: $b
VS.
$a ?? $b
Lorsque votre premier argument est null, il est pratiquement identique, sauf que la fusion nulle ne génère pas E_NOTICE
lorsque vous avez une variable non définie. Le PHP 7.0 Docs de migration a ceci à dire:
L'opérateur de coalescence nul (??) a été ajouté en tant que sucre syntaxique pour le cas courant de devoir utiliser un ternaire en conjonction avec isset (). Il retourne son premier opérande s'il existe et n'est pas NULL; sinon, il retourne son deuxième opérande.
Voici un exemple de code pour illustrer ceci:
<?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";
Et c'est la sortie:
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
Les lignes qui ont la notification sont celles où j'utilise l'opérateur ternaire abrégé, par opposition à l'opérateur de coalescence nul. Cependant, même avec la notification, PHP donnera la même réponse.
Exécutez le code: https://3v4l.org/McavC
Bien sûr, cela suppose toujours que le premier argument est null
. Une fois que ce n'est plus nul, vous vous retrouvez avec des différences en ce sens que l'opérateur ??
renverra toujours le premier argument, alors que le raccourci ?:
ne le ferait que si le premier argument était véridique, et cela dépend de la manière dont PHP taperait -diffuser les choses à un booléen .
Alors:
$a = false ?? 'f';
$b = false ?: 'g';
$a
serait alors égal à false
et $b
égal à 'g'
.
Si vous utilisez l'opérateur de raccourci ternaire comme ceci, un avis sera émis si $_GET['username']
n'est pas défini:
$val = $_GET['username'] ?: 'default';
Au lieu de cela, vous devez faire quelque chose comme ceci:
$val = isset($_GET['username']) ? $_GET['username'] : 'default';
L'opérateur null coalescing est équivalent à l'instruction ci-dessus et renvoie «par défaut» si $_GET['username']
n'est pas défini ou est null
:
$val = $_GET['username'] ?? 'default';
Notez que il ne vérifie pas la véracité . Il vérifie uniquement s'il est défini et non nul.
Vous pouvez également le faire, et la première valeur définie (définie et non null
) sera renvoyée:
$val = $input1 ?? $input2 ?? $input3 ?? 'default';
Maintenant, c’est un bon opérateur de coalescence.
La principale différence est que
Ternary Operator expression expr1 ?: expr3
renvoie expr1
si expr1
est évalué à TRUE
mais d'autre part Null Opérateur Coalescing expression (expr1) ?? (expr2)
.__ est évalué à expr1
si expr1
est pasNULL
Ternary L'opérateurexpr1 ?: expr3
émet un avis si le côté gauche Valeur (expr1)
n'existe pas mais par contre Null Coalescing Operator(expr1) ?? (expr2)
En particulier, n'émet pas d'avis si le La valeur de côté gauche (expr1)
n'existe pas, tout comme isset()
.
TernaryOperator reste associatif
((true ? 'true' : false) ? 't' : 'f');
L'opérateur de coalescence nul est juste associatif
($a ?? ($b ?? $c));
Maintenant, expliquons la différence entre par exemple:
Opérateur ternaire(?:)
$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);
Opérateur de coalescence nul(??)
$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);
Voici le tableau qui explique la différence et la similarité entre '??'
et ?:
Remarque spéciale: l'opérateur de coalescence nul et l'opérateur ternaire est un expression, et qu'il n'évalue pas à une variable, mais à la résultat d'une expression. C'est important de savoir si vous voulez retourne une variable par référence. La déclaration retourne $ foo ?? $ bar; et retourne $ var == 42? $ a: $ b; dans une fonction de renvoi par référence sera donc pas de travail et un avertissement est émis.
Ran le ci-dessous sur le mode interactif php (php -a
sur le terminal). Le commentaire sur chaque ligne montre le résultat.
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"
??
:??
est comme une "porte" qui ne laisse que NULL à travers. NULL
. ??
est identique à ( !isset() || is_null() )
?:
?:
EST COMME UNE PORTE QUI LAISSE anything falsy
TRAVERSER - Y COMPRIS NULL
0
, empty string
, NULL
, false
, !isset()
, empty()
.. tout ce qui sent la fausseté echo ($x ? $x : false)
?:
jettera PHP NOTICE
sur des variables non définies (unset
ou !isset()
)??
et ?:
..?:
quand empty($x)
!empty($x) ? $x : $y
peut être réduite à $x ?: $y
if(!$x) { fn($x); } else { fn($y); }
peut être raccourci à fn(($x ?: $y))
??
quand !isset() || is_null()
$object = $object ?? new objClassName();
L'opérateur ternaire peut être empilé ...
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
Ceci est essentiellement une séquence de:
if( truthy ) {}
else if(truthy ) {}
else if(truthy ) {}
..
else {}
Null Coalese Operator peut être empilé ...
$v = $x ?? $y ?? $z;
Ceci est une séquence de:
if(!isset($x) || is_null($x) ) {}
else if(!isset($y) || is_null($y) ) {}
else {}
En utilisant l'empilement, je peux raccourcir ceci:
if(!isset($_GET['name'])){
if(isset($user_name) && !empty($user_name)){
$name = $user_name;
}else {
$name = 'anonymous';
}
} else {
$name = $_GET['name'];
}
Pour ça:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
Cool, non? :-)
Les deux se comportent différemment en matière de traitement dynamique des données.
Si la variable est vide (''), la fusion nulle traitera la variable comme vraie, mais l'opérateur ternaire abrégé ne le fera pas. Et c'est quelque chose à avoir à l'esprit.
$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';
Et la sortie:
1b
2b
2d
1f
Notice: Undefined variable: e in /in/ZBAa1 on line 21
2f
Lien: https://3v4l.org/ZBAa1
Les deux sont des raccourcis pour des expressions plus longues.
?:
est l'abréviation de $a ? $a : $b
. Cette expression sera évaluée à $ a si $ a est évaluée àTRUE.
??
est l'abréviation de isset($a) ? $a : $b
. Cette expression sera évaluée à $ a si $ a est défini et non nul.
Leurs cas d'utilisation se chevauchent lorsque $ a n'est pas défini ou est nul. Lorsque $ a n'est pas défini, ??
ne produira pas de E_NOTICE, mais les résultats sont identiques. Lorsque $ a est nul, le résultat est le même.
Pour les débutants:
Opérateur de coalescence nul (??)
Tout est vrai sauf null
valeurs et indéfini (attributs de variable/tableau/d'objet)
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"
il s’agit en gros de vérifier que la variable (index de tableau, attribut d’objet, etc.) est existante et non pas null
. semblable à la fonction isset
sténographie de l'opérateur ternaire (?:)
toutes les fausses choses (false
, null
, 0
, chaîne vide) sont fournies comme fausses, mais si c'est un indéfini, elles deviennent également fausses, mais Notice
jette
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: ..
J'espère que cela t'aides
Faites défiler vers le bas this link et affichez la section. Elle vous donne un exemple comparatif, comme indiqué ci-dessous:
<?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';
?>
Cependant, il n'est pas conseillé de chaîner les opérateurs car cela rend plus difficile la compréhension du code lors de sa lecture ultérieure.
L'opérateur de coalescence nul (??) a été ajouté en tant que sucre syntaxique pour le cas courant où il est nécessaire d'utiliser un ternaire conjointement avec isset (). Il retourne son premier opérande s'il existe et n'est pas NULL; sinon, il retourne son deuxième opérande.
Essentiellement, l’utilisation de l’opérateur coalescent rendra la vérification automatique nulle, contrairement à l’opérateur ternaire.
Il semble qu'il y ait des avantages et des inconvénients à utiliser soit ??
, soit ?:
. Le pro à utiliser ?:
est qu’il évalue false et null et "" les mêmes. L'inconvénient est qu'il signale un E_NOTICE si l'argument précédent est null. Avec ??
, le pro, c’est qu’il n’ya pas de E_NOTICE, mais l’inconvénient est qu’il n’évalue pas false et a la même valeur. D'après mon expérience, des personnes ont commencé à utiliser les termes null et false de manière interchangeable, mais elles ont fini par modifier leur code afin de les rendre compatibles avec l'utilisation de null ou de false, mais pas des deux. Une alternative consiste à créer une condition ternaire plus élaborée: (isset($something) or !$something) ? $something : $something_else
.
Voici un exemple de différence entre l'opérateur ??
qui utilise les valeurs null et false:
$false = null;
$var = $false ?? "true";
echo $var . "---<br>";//returns: true---
$false = false;
$var = $false ?? "true";
echo $var . "---<br>"; //returns: ---
En élaborant sur l'opérateur ternaire, nous pouvons toutefois faire en sorte qu'une chaîne "" vide se comporte comme s'il s'agissait d'un caractère nul sans envoyer d'e-notot:
$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---
Personnellement, je pense que ce serait vraiment bien si une future version de PHP incluait un autre nouvel opérateur: :?
qui remplaçait la syntaxe ci-dessus. C'est-à-dire: // $var = $false :? "true";
Cette syntaxe évaluerait nullement, "false" et "" de la même manière et ne lancerait pas un E_NOTICE ...
Les autres réponses vont en profondeur et donnent de bonnes explications. Pour ceux qui cherchent une réponse rapide,
$a ?: 'fallback'
est $a ? $a : 'fallback'
tandis que
$a ?? 'fallback'
est $a = isset($a) ? $a : 'fallback'
La principale différence serait que l'opérateur de gauche est:
0
, ''
, false
, []
, ...)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
n'effectue que deux tâches: il vérifie whether the variable is set
et whether it is null
. Regardez l'exemple suivant:
<?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'
L'exemple de code ci-dessus indique que Null Coalescing operator
traite une variable non existante et une variable définie sur NULL
de la même manière.
Null Coalescing operator
est une amélioration par rapport au ternary operator
. Jetez un coup d'oeil à l'extrait de code suivant comparant les deux:
<?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.
La différence entre les deux réside donc dans le fait que l'opérateur Null Coalescing operator
est conçu pour gérer des variables non définies mieux que le ternary operator
. Considérant que, le ternary operator
est un raccourci pour if-else
.
Null Coalescing operator
n'est pas destiné à remplacer ternary operator
, mais dans certains cas d'utilisation, comme dans l'exemple ci-dessus, il vous permet d'écrire du code en clair avec moins de tracas.
Crédits: http://dwellupper.io/post/6/php7-null-coalescing-operator-usage-and-examples
Lorsque vous utilisez des superglobales telles que $ _GET ou $ _REQUEST, vous devez être conscient du fait qu’elles peuvent être une chaîne vide .
$username = $_GET['user'] ?? 'nobody';
échouera car la valeur de $ username est maintenant une chaîne vide.
Ainsi, lorsque vous utilisez $ _GET ou même $ _REQUEST, vous devez utiliser l'opérateur ternaire à la place:
$username = (!empty($_GET['user'])?$_GET['user']:'nobody';
Maintenant, la valeur de $ username est "personne" comme prévu.