?: operator (l '"operatore Elvis") in PHP


258

L'ho visto oggi in alcuni codici PHP:

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

Non ho familiarità con l' ?:operatore utilizzato qui. Sembra un operatore ternario, ma l'espressione per valutare se il predicato è vero è stata omessa. Cosa significa?

Risposte:


529

Valuta l'operando di sinistra se l'operando di sinistra è vero , e l'operando di destra in caso contrario.

In pseudocodice,

foo = bar ?: baz;

si risolve grossolanamente

foo = bar ? bar : baz;

o

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

con la differenza che barverrà valutata una sola volta.

Puoi anche usarlo per fare un "autocontrollo" foocome dimostrato nell'esempio di codice che hai pubblicato:

foo = foo ?: bar;

Questo assegnerà bara fooif fooè null o falsey, altrimenti rimarrà fooinvariato.

Alcuni altri esempi:

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

A proposito, si chiama operatore Elvis .

Operatore Elvis


11
Assicurati che la variabile tra parentesi esista comunque, o genererai un errore. PHP non assumerà semplicemente che abbia un valore nullo qualcosa del genere.
Sto

20
La cosa divertente è che questa risposta forma un ciclo ricorsivo con l'articolo Wiki, che non ha spiegato completamente perché si chiama "operatore Elvis".
Apparendo divertente il

41
Un po 'meno di operazione, un po' più di espressione per favore.
aalaap,

2
Perché non usare solo a ||. Quindi blah || 'default'?
Noitidart,

10
@Noitidart Perché, a differenza di JS dove restituisce l'operando di verità più a sinistra, in PHP l' ||operatore restituisce sempre un valore booleano.
ksadowski,

58

Vedi i documenti :

Da PHP 5.3, è possibile tralasciare la parte centrale dell'operatore ternario. L'espressione expr1 ?: expr3restituisce expr1se viene expr1valutata TRUEe in caso expr3contrario.


10
Hanno bisogno di un nuovo autore di documenti perché inevitabilmente qualcuno chiederà cosa è successo a expr2. L'ho appena provato.
John K,

7
Che diamine? L'ho scoperto ora, subito dopo l'aggiornamento a PHP 7? Avrei potuto usarlo per anni!
Buttle Butkus,

TBH, i documenti sono corretti. Quello che è successo expr2è che è semplicemente scomparso e non viene valutato. $this->expensiveComputation() ?: "nope"non è identico a $this->expensiveComputation() ? $this->expensiveComputation() : "nope"- expr1 viene valutato solo una volta.
Piskvor lasciò l'edificio il

18

Fare attenzione con le matrici. Dobbiamo scrivere una variabile di controllo dopo ?, perché:

  $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

aggiornato

Da RFC. In futuro (in PHP 7) l'operatore Null Coalesce Operator lo farà, ad esempio:

$param1 = $params['param1'] ?? null;
// Equivalent to:  $param1 = isset($params['param1']) ? $params['param1'] : null;

1
Questo non risponde alla domanda, né è utile a chiunque cerchi di capire quando utilizzare Elvis Operator.
Mark Amery, l'

7
@Mark Amery hmm .. Davvero? Non è utile? Hai davvero lavorato con PHP e hai esaminato migliaia di casi nell'uso per accedere ai vari array con ternario? Ok, ho cambiato il testo in "Attento agli array .."
voodoo417,

quindi nullità ed elvis sono uguali?
Nabeel Khan,

7
@NabeelKhan No! E questo rende l'operatore Elvis un po 'inutile in PHP imo. L'operatore Elvis valuta un'espressione e, se è vera, la restituisce altrimenti restituisce l'ultima parte. Poiché PHP è poco tipizzato, molte cose saranno vere o false, e molto probabilmente le cose non saranno quelle che desideri. Vale a dire: vuoi impostare un valore predefinito su una variabile se non è definito, utilizzando l'operatore Elvis PHP ti dirà che 0 non è definito, ma potresti volerlo 0 ... Ecco perché PHP 7 otterrà l'operatore Null Coalesce , Testerà rigorosamente la tua variabile su null, quindi PHP dirà che 0 non è indefinito.
Gregoire D.

1
@FuscaSoftware: l'utilizzo della soppressione degli errori in questo modo non è una buona idea nella mia esperienza.
TeeHays,

8

Un'altra considerazione importante: Elvis Operator interrompe il processo di tokenizzazione di Zend Opcache. L'ho trovato nel modo più duro! Anche se questo potrebbe essere stato risolto nelle versioni successive, posso confermare che questo problema esiste in PHP 5.5.38 (con Zend Opcache integrato v7.0.6-dev).

Se scopri che alcuni dei tuoi file 'rifiutano' di essere memorizzati nella cache in Zend Opcache, questo potrebbe essere uno dei motivi ... Spero che questo ti aiuti!


4

Sì, questo è nuovo in PHP 5.3. Restituisce il valore dell'espressione di test se viene valutato come VERO o il valore alternativo se viene valutato come FALSO.


2
Sottilmente sbagliato / fuorviante; nessuno degli operandi deve essere un valore booleano. Ciò che conta è se il primo valore è vero , non se lo è TRUE.
Mark Amery, l'

@MarkAmery Chiarito. Dovrebbe essere abbastanza difficile fraintenderlo in questo modo.
Atli,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.