Desde PHP 7 podemos utilizar dos nuevos operadores que nos harán la vida un poco más fácil en la comprobación y comparación de valores. Uno es el null coalesce (fusión de null) y el otro es el operador de comparación combinada conocido como spaceship. Veamos un poco más en detalle cada uno y como utilizarlos.

1

Null coalesce: ??

Este operador, cuyo nombre se puede traducir como “fusión de null”, es una mejora del conocido como operador Elvis, que es a su vez una mejora del operador ternario.

Un ejemplo muy habitual del operador ternario podría ser algo así:

$var = isset($_GET['foo']) ? $_GET['foo'] : "default_value";

El operador Elvis (por su simbología ?:), lo pone más fácil:

$var = $_GET['foo'] ?: "default_value";

Pero en este último caso obtendríamos un error tipo E_NOTICE si $_GET['foo'] no está definido. El nuevo operador fusión de null soluciona este problema y podemos hacer lo siguiente:

$var = $_GET['foo'] ?? "default_value";
// equivalente al operador ternario
// $var = isset($_GET['foo']) ? $_GET['foo'] : "default_value";

La diferencia: el operador fusión de null devuelve el valor del primer operando si existe y no es NULL, de lo contrario devuelve el segundo operando. Es decir, se comprueba isset() en el primer operando y por ello expresiones como $_GET['foo'] ?? "" no generarán ningún tipo de error.

Y, al igual que en el operador ternario, se pueden utilizar expresiones, funciones y llamadas a métodos. Por ejemplo:

$default_object = 0;
$id = 452;
$object = ObjectModel::get($id) ?? $default_object;
// equivalente a
// if (($object = ObjectModel::get($id)) === NULL) { $object = $default_object; }

Y además se pueden encadenar todos los operandos que deseemos y se leerán de izquierda a derecha:

$a = NULL;
$b = NULL;
$c = 100;
$d = $a ?? $b ?? $c;
var_dump( $d ); // int(100)

En este último ejemplo, podemos ver como el null coalesce nos permite construir expresiones en las que dar prioridad a una secuencia de datos y a la vez proveer un valor predeterminado, un fallback en caso de que no existan los valores anteriores. Muy útil para comprobar user inputs, configuraciones, etc.

2

Spaceship: <=>

El operador de comparación combinada, de apodo spaceship (nave espacial) por la forma de su símbolo <=>, es un operador binario pero que realiza tres comparaciones. Consta de dos operandos separados por <=> y comprueba si:

  • Operando de la izquierda es menor (<) que el operando de la derecha: devuelve el valor -1.
  • Ambos operandos son iguales (=): devuelve el valor 0 (cero).
  • Operando de la izquierda es mayor (>) que el operando de la derecha: devuelve el valor 1.

Por ejemplo:

function comparison( $a, $b ) {
    return $a <=> $b;
}

var_dump( comparison( 2, 3 ) ); // -1
var_dump( comparison( 3, 2 ) ); // 1
var_dump( comparison( 8, 8 ) ); // 0
var_dump( comparison( 4.2, 0.8 ) ); // 1
var_dump( comparison( "c", "a" ) ); // 1
var_dump( comparison( [1,2,3], [1,2,3] ) ); // 0
var_dump( comparison( [1,2,4], [1,2,3] ) ); // 1

A disfrutar!!

  • Elkin

    Hola,

    Gracias por compartir, pero tengo una duda al respecto.
    Al hacer esto: $object = ObjectModel::get($id) ?? $default_obj;
    No sería lo mismo que esto: $object = ObjectModel::get($id) || $default_object;

    O cual es la diferencia?

    Gracias

    • No son lo mismo. Cómo comento en ese snippet, esto:

      $object = ObjectModel::get($id) ?? $default_obj;

      es equivalente a esto:

      if ( ( $object = ObjectModel::get( $id ) ) === NULL) {
      $object = $default_object;
      }

      La variable $object toma el valor que devuelve ObjectModel::get( $id ) o el valor de $default_object.

      Pero esto:

      $object = ObjectModel::get($id) || $default_object;

      Es equivalente a:

      if ( ObjectModel::get( $id ) ) {
      $object = true;
      } else {
      $object = false;
      }

      La variable $object toma un valor lógico true o false.

  • Muy interesante.. gracias por la información, no estaba al tanto de éstos operadores.

    Estoy leyendo tu blog y estoy aprendiendo cosas interesantes.

    Saludos y mucha suerte!.