?: operador (el 'operador de Elvis') en PHP

258

Vi esto hoy en algún código PHP:

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

No estoy familiarizado con el ?:operador que se utiliza aquí. Parece un operador ternario, pero se ha omitido la expresión para evaluar si el predicado es verdadero. Qué significa eso?

alpha_juno
fuente

Respuestas:

529

Evalúa el operando izquierdo si el operando izquierdo es verdadero , y el operando derecho de lo contrario.

En pseudocódigo,

foo = bar ?: baz;

aproximadamente resuelve a

foo = bar ? bar : baz;

o

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

con la diferencia que barsolo se evaluará una vez.

También puede usar esto para hacer una "autocomprobación" de foocomo se demuestra en el ejemplo de código que publicó:

foo = foo ?: bar;

Esto asignará bara foosi fooes nulo o falsey, de lo contrario se dejará foosin cambios.

Algunos ejemplos más:

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

Por cierto, se llama el operador de Elvis .

Operador de Elvis

BalusC
fuente
11
Sin embargo, asegúrese de que la variable entre paréntesis exista, o va a generar un error. PHP no solo asumirá que tiene un valor de nullo cualquier cosa. Solo
digo
20
Lo curioso es que esta respuesta forma un bucle recursivo con el artículo de Wiki, que no explica completamente por qué se llama el "operador de Elvis".
aparentemente divertido
41
Un poco menos de operación, un poco más de expresión, por favor.
aalaap
2
¿Por qué no solo usar a ||. Entonces blah || 'default'?
Noitidart
10
@Noitidart Porque, a diferencia de JS donde devuelve el operando verdadero más a la izquierda, en PHP el ||operador siempre devuelve un booleano.
ksadowski
58

Ver los documentos :

Desde PHP 5.3, es posible omitir la parte media del operador ternario. La expresión expr1 ?: expr3vuelve expr1si se expr1evalúa como TRUE, y de lo expr3contrario.

Yacoby
fuente
10
Necesitan un nuevo escritor de documentos porque inevitablemente alguien preguntará qué pasó con expr2. Lo acabo de decir.
John K
77
¿Que demonios? ¿Acabo de descubrir esto ahora, justo después de actualizar a PHP 7? ¡Podría haber estado usando esto por años!
Buttle Butkus
TBH, los documentos son correctos. Lo que sucedió expr2es que simplemente desapareció y no se evalúa. $this->expensiveComputation() ?: "nope"no es idéntico a $this->expensiveComputation() ? $this->expensiveComputation() : "nope"- expr1 solo se evalúa una vez.
Piskvor salió del edificio el
18

Tenga cuidado con las matrices. Debemos escribir una variable de verificación después ?, porque:

  $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

Actualizado

De RFC. En el futuro (en PHP 7) el operador Null Coalesce Operator lo hará, por ejemplo:

$param1 = $params['param1'] ?? null;
// Equivalent to:  $param1 = isset($params['param1']) ? $params['param1'] : null;
voodoo417
fuente
1
Esto no responde la pregunta, ni es útil para cualquiera que intente entender cuándo usar el Operador de Elvis.
Mark Amery
77
@ Mark Amery hmm .. ¿En serio? ¿No es útil? ¿Realmente trabajó con PHP y analizó miles de casos al usar para acceder a los vars de la matriz con ternary? Ok, cambié el texto a "Tenga cuidado con las matrices .."
voodoo417
entonces nulo coalesce y elvis son lo mismo?
Nabeel Khan
77
@NabeelKhan ¡No! Y eso hace que el operador de Elvis sea inútil en PHP imo. El operador de Elvis evalúa una expresión y, si es verdadera, la devuelve; de ​​lo contrario, devuelve la última parte. Como PHP tiene un tipo bajo, muchas cosas serán verdaderas o falsas, y lo más probable es que las cosas no sean lo que quieres. Es decir: si desea establecer un valor predeterminado para una variable si no está definido, el uso del operador de Elvis PHP le dirá que 0 no está definido, pero es posible que desee que 0 ... Es por eso que PHP 7 obtendrá el operador de fusión nula , Probará estrictamente su variable contra nulo, por lo que PHP dirá que 0 no está indefinido.
Gregoire D.
1
@FuscaSoftware: Usar mipresión de errores como este no es una buena idea en mi experiencia.
TeeHays
8

Otra consideración importante: el operador de Elvis interrumpe el proceso de tokenización de Zend Opcache. ¡Encontré esto de la manera difícil! Si bien esto puede haberse solucionado en versiones posteriores, puedo confirmar que este problema existe en PHP 5.5.38 (con Zend Opcache v7.0.6-dev incorporado).

Si encuentra que algunos de sus archivos "se niegan" a almacenarse en caché en Zend Opcache, esta puede ser una de las razones ... ¡Espero que esto ayude!

Prasad Paradkar
fuente
4

Sí, esto es nuevo en PHP 5.3. Devuelve el valor de la expresión de prueba si se evalúa como VERDADERO o el valor alternativo si se evalúa como FALSO.

Atli
fuente
2
Sutilmente equivocado / engañoso; ninguno de los operandos debe ser booleano. Lo que importa es si el primer valor es verdadero , no si lo es TRUE.
Mark Amery
@MarkAmery aclarado. Debería ser bastante difícil malinterpretarlo de esta manera.
Atli