?: opérateur («l'opérateur Elvis») en PHP

258

J'ai vu cela aujourd'hui dans du code PHP:

$items = $items ?: $this->_handle->result('next', $this->_result, $this);

Je ne connais pas l' ?:opérateur utilisé ici. Il ressemble à un opérateur ternaire, mais l'expression à évaluer si le prédicat est vrai a été omise. Qu'est-ce que ça veut dire?

alpha_juno
la source

Réponses:

529

Il évalue à l'opérande gauche si l'opérande gauche est véridique , et l'opérande droit sinon.

En pseudocode,

foo = bar ?: baz;

résout grosso modo

foo = bar ? bar : baz;

ou

if (bar) {
    foo = bar;
} else {
    foo = baz;
}

avec la différence qui barne sera évaluée qu'une seule fois.

Vous pouvez également l'utiliser pour effectuer une "auto-vérification" foocomme illustré dans l'exemple de code que vous avez publié:

foo = foo ?: bar;

Cela affectera barà fooif fooest null ou falsey, sinon il restera fooinchangé.

Quelques exemples supplémentaires:

<?php
    var_dump(5 ?: 0); // 5
    var_dump(false ?: 0); // 0
    var_dump(null ?: 'foo'); // 'foo'
    var_dump(true ?: 123); // true
    var_dump('rock' ?: 'roll'); // 'rock'
?>

Au fait, cela s'appelle l' opérateur Elvis .

Opérateur Elvis

BalusC
la source
11
Assurez-vous cependant que la variable entre parenthèses existe, sinon vous allez générer une erreur. PHP ne supposera pas simplement qu'il a une valeur de nullou quoi que ce soit. Just sayin '
DanMan
20
Ce qui est drôle, c'est que cette réponse forme une boucle récursive avec l'article du Wiki, qui n'explique pas complètement pourquoi on l'appelle "l'opérateur Elvis".
semblant.amusant le
41
Un peu moins d'opération, un peu plus d'expression s'il vous plaît.
aalaap
2
Pourquoi ne pas simplement utiliser a ||. Alors blah || 'default'?
Noitidart
10
@Noitidart Parce que, contrairement à JS où il renvoie l'opérande véridique le plus à gauche, en PHP l' ||opérateur renvoie toujours un booléen.
ksadowski
58

Voir les documents :

Depuis PHP 5.3, il est possible de laisser de côté la partie centrale de l'opérateur ternaire. L'expression expr1 ?: expr3retourne expr1si expr1évalue à TRUEet expr3autrement.

Yacoby
la source
10
Ils ont besoin d'un nouveau rédacteur de document, car inévitablement quelqu'un demandera ce qui est arrivé à expr2. Je viens de le penser.
John K
7
Que diable? Je viens de le découvrir maintenant, juste après la mise à niveau vers PHP 7? J'aurais pu utiliser ça depuis des années!
Buttle Butkus
TBH, les documents sont corrects. Ce qui expr2est arrivé, c'est qu'il a simplement disparu et n'est pas évalué. $this->expensiveComputation() ?: "nope"n'est pas identique à $this->expensiveComputation() ? $this->expensiveComputation() : "nope"- expr1 n'est évalué qu'une seule fois.
Piskvor a quitté le bâtiment
18

Soyez prudent avec les tableaux. Nous devons écrire une variable de contrôle après ?, car:

  $params = ['param1' => 'value1',
             'param2' => 'value2',
             'param3' => 'value3',];

  $param1 = isset($params['param1'])?:null;
  $param2 = !empty($params['param2'])?:null;
  $param3 = $params['param3']?:null; // get E_NOTICE, if $params['param3'] eq false

  var_dump($param1,$param2,$param3);
  true // would like to expect `value1`
  true // would like to expect `value2`
  param3 // properly, but problem above

Actualisé

De RFC. Dans le futur (en PHP 7) l'opérateur Null Coalesce Operator le fera, par exemple:

$param1 = $params['param1'] ?? null;
// Equivalent to:  $param1 = isset($params['param1']) ? $params['param1'] : null;
voodoo417
la source
1
Cela ne répond pas à la question et n'est utile à personne qui essaie de comprendre quand utiliser l'opérateur Elvis.
Mark Amery
7
@Mark Amery hmm .. Vraiment? N'est-ce pas utile? Avez-vous vraiment travaillé avec PHP et examiné des milliers de cas d'utilisation pour accéder aux variables de tableau avec ternaire? Ok, j'ai changé le texte en "Soyez prudent avec les tableaux .."
voodoo417
donc coalesce nul et elvis sont les mêmes?
Nabeel Khan
7
@NabeelKhan Non! Et cela rend l'opérateur Elvis un peu inutile dans PHP imo. L'opérateur Elvis évalue une expression et si elle est vraie, elle la renvoie sinon elle retourne la dernière partie. Comme PHP est de type bas, beaucoup de choses seront vraies ou fausses, et les choses ne seront probablement pas ce que vous voulez. C'est-à-dire que vous voulez définir une valeur par défaut pour une variable si elle n'est pas définie, en utilisant l'opérateur Elvis PHP dira que 0 n'est pas défini, mais vous voudrez peut-être que 0 ... C'est pourquoi PHP 7 obtiendra l'opérateur Null Coalesce , Il testera strictement votre variable contre null, donc PHP dira que 0 n'est pas indéfini.
Gregoire D.
1
@FuscaSoftware: L'utilisation de la suppression d'erreurs comme celle-ci n'est pas une bonne idée dans mon expérience.
TeeHays
8

Autre considération importante: l'opérateur Elvis interrompt le processus de tokenisation Zend Opcache. J'ai trouvé ça à la dure! Bien que cela ait pu être corrigé dans les versions ultérieures, je peux confirmer que ce problème existe en PHP 5.5.38 (avec Zend Opcache v7.0.6-dev intégré).

Si vous trouvez que certains de vos fichiers «refusent» d'être mis en cache dans Zend Opcache, cela peut être l'une des raisons ... J'espère que cela vous aidera!

Prasad Paradkar
la source
4

Oui, c'est nouveau dans PHP 5.3. Il renvoie soit la valeur de l'expression de test si elle est évaluée comme TRUE, soit la valeur alternative si elle est évaluée comme FALSE.

Atli
la source
2
Subtilement faux / trompeur; aucun opérande ne doit être un booléen. Ce qui importe est de savoir si la première valeur est véridique , et non si elle l'est TRUE.
Mark Amery
@MarkAmery Clarified. Il devrait être assez difficile de mal l'interpréter de cette façon.
Atli