W3docs

try

Aprende cómo PHP try/catch/finally maneja excepciones. Cubre múltiples bloques catch, tipos unión, relanzamiento y errores comunes.

La palabra clave try en PHP

La palabra clave try marca un bloque de código que puede lanzar una excepción — un objeto que señala que algo salió mal y la ejecución normal no puede continuar. Cuando se lanza una excepción dentro de un bloque try, PHP deja de ejecutar el resto de ese bloque y busca un bloque catch coincidente para manejarla. Un bloque finally opcional se ejecuta después sin importar lo que haya ocurrido.

Esta página cubre la sintaxis de try/catch/finally, cómo se emparejan múltiples bloques catch, cómo capturar varios tipos de excepciones a la vez, el relanzamiento y los errores comunes que suelen confundir a los desarrolladores. Si eres nuevo en el concepto de lanzar errores, lee primero Excepciones en PHP.

Sintaxis

try {
  // Code that may throw an exception
} catch (ExceptionType $e) {
  // Code that runs if an exception of ExceptionType (or a subclass) is thrown
} finally {
  // Optional: always runs, whether or not an exception was thrown
}

Un bloque try debe ir seguido de al menos un bloque catch, o un bloque finally, o ambos — un try solo es un error de sintaxis. La variable en catch (ExceptionType $e) contiene el objeto de excepción lanzado, al que puedes consultar con métodos como $e->getMessage().

Un primer ejemplo

La función a continuación lanza una excepción cuando se le pide dividir entre cero. El bloque try la llama, el bloque catch reporta el problema y finally siempre se ejecuta:

<?php

function divide($dividend, $divisor)
{
  if ($divisor == 0) {
    throw new Exception("Cannot divide by zero.");
  }
  return $dividend / $divisor;
}

try {
  $result = divide(10, 0);
  echo $result;            // skipped — divide() threw before returning
} catch (Exception $e) {
  echo "Error: " . $e->getMessage() . PHP_EOL;
} finally {
  echo "Done." . PHP_EOL;
}

Resultado:

Error: Cannot divide by zero.
Done.

Observa que echo $result; nunca se ejecuta: en cuanto divide(10, 0) lanza la excepción, el control salta directamente al bloque catch. El bloque finally se ejecuta después. Si llamas a divide(10, 2) en su lugar, no se lanza ninguna excepción, el bloque try imprime 5 y finally sigue imprimiendo Done..

Múltiples bloques catch

Un único try puede ir seguido de varios bloques catch. PHP los revisa de arriba a abajo y ejecuta el primero cuyo tipo coincida con la excepción lanzada (la coincidencia incluye subclases). Lista los tipos más específicos antes que los más generales — un catch (Exception $e) al inicio se tragaría todo lo que viene debajo.

<?php

try {
  $value = "5";
  if (!is_int($value)) {
    throw new TypeError("Expected an integer.");
  }
} catch (TypeError $e) {
  echo "Type problem: " . $e->getMessage() . PHP_EOL;
} catch (Exception $e) {
  echo "Other problem: " . $e->getMessage() . PHP_EOL;
}

Resultado:

Type problem: Expected an integer.

Capturar varios tipos en un solo bloque

Cuando dos tipos de excepción deben manejarse de la misma manera, combínalos con una barra vertical (|) — una característica añadida en PHP 7.1 — en lugar de duplicar el bloque:

<?php

try {
  throw new RuntimeException("Network timed out.");
} catch (RuntimeException | LogicException $e) {
  echo "Handled: " . $e->getMessage() . PHP_EOL;
}

Resultado:

Handled: Network timed out.

Comportamiento de finally

El bloque finally se ejecuta incluso si el bloque try o catch ejecuta un return. Esto lo convierte en el lugar adecuado para la limpieza — cerrar archivos, liberar bloqueos, revertir una transacción — que debe ocurrir en todos los caminos:

<?php

function readConfig()
{
  try {
    return "config loaded";
  } finally {
    echo "Cleanup ran." . PHP_EOL;
  }
}

echo readConfig() . PHP_EOL;

Resultado:

Cleanup ran.
config loaded

El bloque finally se ejecuta antes de que la función retorne realmente su valor. Evita hacer un return dentro del propio finally: un return ahí anula el valor de try/catch y descarta silenciosamente cualquier excepción que estuviera siendo lanzada.

Relanzar una excepción

Un bloque catch puede hacer un trabajo parcial — registrar el error, agregar contexto — y luego relanzar la excepción para que el llamador en un nivel superior decida qué hacer. Usa throw $e; para relanzar el mismo objeto:

<?php

try {
  try {
    throw new Exception("Disk full.");
  } catch (Exception $e) {
    echo "Logging: " . $e->getMessage() . PHP_EOL;
    throw $e; // hand it to the outer handler
  }
} catch (Exception $e) {
  echo "Outer handler: " . $e->getMessage() . PHP_EOL;
}

Resultado:

Logging: Disk full.
Outer handler: Disk full.

Errores comunes

  • try necesita un compañero. Un bloque try solo no se puede analizar — combínalo con al menos un catch o un finally.
  • Los errores no son todos excepciones. Muchas advertencias en tiempo de ejecución (una variable no definida, un fopen() fallido) no se lanzan como excepciones, por lo que catch no las verá. Usa set_error_handler() o comprueba los valores de retorno para esos casos. Los objetos Error fatales (como TypeError) pueden capturarse porque implementan Throwable.
  • Ordena los bloques catch de más específico a más general. Un catch (Exception $e) amplio colocado primero oculta todos los bloques siguientes.
  • No los ignores silenciosamente. Un bloque catch vacío oculta el fallo; como mínimo, registra $e->getMessage() para que el problema sea visible.
  • finally puede enmascarar excepciones. Retornar desde finally descarta tanto el valor de retorno de try como cualquier excepción que estuviera en vuelo.

¿Cuándo debo usar try?

Recurre a try/catch cuando un fallo es excepcional y el código que llama puede reaccionar razonablemente ante él: una conexión a la base de datos que cae, una API que devuelve un error, una entrada de usuario inválida que quieres rechazar de forma limpia. Para el flujo de control ordinario (¿se encontró una clave en un array? ¿está vacío un string?), usa condicionales normales — las excepciones son para el camino anormal, no para las bifurcaciones cotidianas.

Relacionado

Práctica

Práctica
¿Qué etiqueta se usa en PHP para iniciar un bloque de código?
¿Qué etiqueta se usa en PHP para iniciar un bloque de código?
Was this page helpful?