PHP

Operador ternario en PHP

Autorangel cruz
Actualizado
Publicado
Lectura5 min de lectura
Operador ternario en PHP

Este artículo forma parte de la guía de operadores en PHP, donde repaso todas las categorías (aritméticos, comparación, lógicos y más). Aquí me enfoco en el ternario.

¿Qué es el operador ternario en PHP?

El operador ternario en PHP es un operador condicional que resume un if-else en una sola línea: evalúa una condición y devuelve el primer valor si es verdadera o el segundo si es falsa.

Su sintaxis es:

condición ? valor_si_verdadero : valor_si_falso;

Ejemplo:

$edad = 20;
echo ($edad >= 20) ? 'Pasa' : 'Fuera'; // Pasa

Las tres partes son:

  • condición: la expresión que se evalúa y retorna un valor booleano.
  • valor si verdadero: lo que se devuelve cuando la condición es true.
  • valor si falso: lo que se devuelve cuando la condición es false.

La versión corta del operador ternario

La sintaxis del operador ternario corto se puede utilizar omitiendo la parte central del operador ternario para una evaluación rápida y abreviada. También se conoce como el "Operador Elvis"

Ejemplo:

$val = $_GET['user'] ?: 'default';

Es el operador ternario con el operando del medio omitido: devuelve el primero si es verdadero y, si no, evalúa y devuelve el segundo. Sirve para quitar la redundancia de escribir dos veces la misma variable.

Ojo con un detalle que se repite mal en muchos tutoriales: si $_GET['user'] no existe, ?: no falla, pero sí emite un Warning: Undefined array key antes de devolver 'default'. El valor sale bien y el aviso ensucia los logs. Ese es exactamente el hueco que llena ??.

Operador de fusión de null (??)

El null coalescing hace lo mismo que el Elvis pero sin quejarse cuando la variable no está definida, porque lleva un isset() incorporado:

$user = $_GET['user'] ?? 'nobody';

La regla práctica para elegir entre los tres:

Operador Qué evalúa Cuándo usarlo
? : La condición que le escribas Cuando quieres devolver algo distinto del valor evaluado
?: Si el valor es truthy El valor existe y solo quieres cubrir el caso vacío ('', 0)
?? Si el valor existe y no es null El valor puede no estar definido, como en $_GET o un array

Cuidado con la diferencia entre las dos últimas: 0 ?: 'x' devuelve 'x' porque 0 es falsy, mientras que 0 ?? 'x' devuelve 0, porque 0 sí está definido. El detalle completo, incluido el operador de asignación ??=, está en el artículo de null coalescing en PHP.

El if corto y sus límites

Al ternario se le llama también "if corto" o "if abreviado", y ahí está su trampa: por parecerse a un if la gente lo anida, y desde PHP 8.0 anidar ternarios sin paréntesis es un error fatal, no un aviso:

// Fatal error: Unparenthesized `a ? b : c ? d : e` is not supported
echo $a ? 'a' : ($b ? 'b' : 'c'); // así sí, con paréntesis explícitos

Si necesitas paréntesis para que se entienda, probablemente lo que necesitas es un if normal o un match. El ternario gana cuando cabe de un vistazo en una línea.

Cuatro casos donde de verdad gana

Clase CSS según un estado. El caso más frecuente en cualquier vista:

$statusClass = $order->status === 'completed' ? 'text-green-600' : 'text-yellow-600';
 
echo "<span class='$statusClass'>{$order->status}</span>";

Pluralizar. Dos ternarios alineados se leen como una pequeña tabla de decisión:

$label  = $count === 1 ? 'producto' : 'productos';
$suffix = $count === 1 ? ''         : 's';
 
echo "$count $label agregado$suffix";
// "1 producto agregado" | "5 productos agregados"

Leer una clave que puede no existir. Aquí el ternario clásico sobra, porque ?? ya lleva el isset() dentro:

// Lo que se escribía antes de PHP 7
$timezone = isset($config['timezone']) ? $config['timezone'] : 'UTC';
 
// Lo mismo, sin el isset
$timezone = $config['timezone'] ?? 'UTC';
 
// Encadenado: devuelve el primer valor que exista y no sea null
$timezone = $config['timezone'] ?? $userPrefs['timezone'] ?? 'UTC';

Ese encadenamiento es uno de los patrones más útiles de PHP 7 en adelante. Ojo con un error habitual al intentar hacer lo mismo con ||, porque en PHP ese operador devuelve un booleano, no el valor:

$avatar = $user->avatar || $user->gravatar ?: '/default.png';  // devuelve true, no una URL
$avatar = $user->avatar ?: $user->gravatar ?: '/default.png';  // así sí

Dentro de un array, para construir una respuesta sin armarla por partes:

$response = [
    'success' => true,
    'data'    => $user ? ['id' => $user->id, 'name' => $user->name] : null,
    'message' => $user ? 'Usuario encontrado' : 'Usuario no encontrado',
];

También encaja bien en arrow functions, donde todo el cuerpo tiene que ser una sola expresión:

$conEtiqueta = array_map(
    fn($p) => [...$p, 'label' => $p['stock'] > 0 ? 'Disponible' : 'Sin stock'],
    $productos
);

Cuándo NO usar el operador ternario

El ternario mejora el código cuando la condición es simple. Hay cuatro casos donde lo empeora:

Cuando cada rama tiene efectos secundarios. Si los dos lados ejecutan consultas, logs o eventos, el ternario esconde que hay dos caminos de ejecución distintos:

// Esconde que son dos operaciones diferentes
$result = $isAdmin ? $this->loadAdminData() : $this->loadUserData();

Cuando pasa de dos niveles de anidamiento. A partir de ahí es un acertijo. Extrae la lógica a una función o usa match.

Cuando hay negaciones dobles. !isset($a) ? $b : $c ya cuesta de leer.

Cuando el equipo no lo usa. Un if-else de cuatro líneas que todo el mundo entiende vale más que un ternario que genera dudas en la revisión.

Ternario o match (PHP 8+)

Para varias condiciones sobre el mismo valor, match gana siempre:

// Ternario anidado: aguantable con tres casos, ilegible con cinco
$color = ($status === 'active') ? 'green'
       : (($status === 'pending') ? 'yellow' : 'red');
 
// match: más claro, y compara con === por defecto
$color = match($status) {
    'active'  => 'green',
    'pending' => 'yellow',
    default   => 'red',
};

Esa comparación estricta es la otra ventaja: match no hace las conversiones de tipo silenciosas que el ternario con == sí permite. Y si ningún caso coincide y no hay default, lanza un UnhandledMatchError en vez de seguir con un valor inesperado.

El resto de los operadores, con el mismo nivel de detalle, están en la guía de PHP.

Preguntas frecuentes

¿Qué es el operador ternario?

Es un operador condicional de tres operandos que resume un if-else en una sola expresión: condición ? valor_si_verdadero : valor_si_falso. Se llama ternario porque toma tres operandos, frente a los binarios como + o &&. Existe con la misma sintaxis en PHP, JavaScript, Java, C y C#.

¿Cómo se hace un if en una línea en PHP?

Con el ternario: $estado = $activo ? 'Sí' : 'No';. Si solo quieres cubrir el caso de que un valor esté vacío, usa ?:, y si puede no estar definido, ??.

¿Cuál es la diferencia entre ?: y ?? en PHP?

?: comprueba si el valor es truthy y avisa con un warning si la variable no existe. ?? comprueba si existe y no es null, sin warning. Con 0: 0 ?: 'x' devuelve 'x', mientras que 0 ?? 'x' devuelve 0.

¿Se pueden anidar operadores ternarios?

Sí, pero desde PHP 8.0 hay que poner los paréntesis de forma explícita o el código no compila: Unparenthesized a ? b : c ? d : e is not supported. Si la expresión pide paréntesis para leerse, conviene un if o un match.