Excepciones

Tabla de contenidos

PHP tiene un modelo de excepciones similar al de otros lenguajes de programación. Una excepción puede ser lanzada ("thrown"), y atrapada ("catched") dentro de PHP. El código puede estar dentro de un bloque try para facilitar la captura de excepciones potenciales. Cada bloque try debe tener al menos un bloque catch o finally correspondiente.

Si se lanza una excepción y el alcance de la función actual no tiene un bloque catch, la excepción "subirá" por la pila de llamadas hasta encontrar un bloque catch que coincida. Todos los bloques finally que encuentre en el camino se ejecutarán. Si la pila de llamadas se desenrolla hasta el alcance global sin encontrar un bloque catch coincidente, el programa terminará con un error fatal, a menos que se haya configurado un manejador de excepciones global.

El objeto lanzado debe ser un instanceof Throwable. Intentar lanzar un objeto que no lo sea resultará en un error fatal de PHP.

A partir de PHP 8.0.0, la palabra clave throw es una expresión y puede usarse en cualquier contexto de expresión. En versiones anteriores, era una declaración y debía estar en su propia línea.

catch

Se pueden usar múltiples bloques catch para atrapar diferentes clases de excepciones. La ejecución normal (cuando no es lanzada ninguna excepción dentro del bloque try) continuará después del último bloque catch definido en la sencuencia. Las excepciones pueden ser lanzadas ("thrown") (o relanzadas) dentro de un bloque catch.

Cuando una excepción es lanzada, el código siguiente a la declaración no será ejecutado, y PHP intentará encontrar el primer bloque catch coincidente. Si una excepción no es capturada, se emitirá un Error Fatal de PHP con un mensaje "Uncaught Exception ..." ("Excepción No Capturada"), a menos que se haya definido un manejador con set_exception_handler().

finally

En PHP y posterior, se puede utilizar un bloque finally después o en lugar de los bloques catch. El código de dentro del bloque finally siempre se ejecutará después de los bloques try y catch, independientemente de que se haya lanzado una excepción o no, y antes de que la ejecución normal continúe.

Manejador global de excepciones

Si se permite que una excepción suba hasta el alcance global, puede ser capturada por un manejador global de excepciones si está configurado. La función set_exception_handler() puede establecer una función que será llamada en lugar de un bloque catch si no se invoca ningún otro bloque. El efecto es esencialmente el mismo que si todo el programa estuviera envuelto en un bloque try-catch con esa función como el catch.

Notas

Nota:

Las funciones internas de PHP utilizan principalmente la Información de Errores, sólo las extensiones Orientadas a objetos modernas utilizan excepciones. Sin embargo, los errores se pueden traducir a excepciones simplemente con ErrorException.

Ejemplo #1 Convertir el informe de errores a excepciones

<?php
function exceptions_error_handler($severity, $message, $filename, $lineno) {
throw new
ErrorException($message, 0, $severity, $filename, $lineno);
}

set_error_handler('exceptions_error_handler');
?>

Sugerencia

La Biblioteca Estándar de PHP (SPL) proporciona una buena cantidad de excepciones integradas.

Ejemplos

Ejemplo #2 Lanzar una Excepción

<?php
function inverso($x) {
if (!
$x) {
throw new
Exception('División por cero.');
}
return
1/$x;
}

try {
echo
inverso(5) . "\n";
echo
inverso(0) . "\n";
} catch (
Exception $e) {
echo
'Excepción capturada: ', $e->getMessage(), "\n";
}

// Continuar la ejecución
echo 'Hola Mundo\n';
?>

El resultado del ejemplo sería:

0.2
Excepción capturada: División por cero.
Hola Mundo

Ejemplo #3 Manejo de excepciones con un bloque finally

<?php
function inverse($x) {
if (!
$x) {
throw new
Exception('División por cero.');
}
return
1/$x;
}

try {
echo
inverse(5) . "\n";
} catch (
Exception $e) {
echo
'Excepción capturada: ', $e->getMessage(), "\n";
} finally {
echo
"Primer finally.\n";
}

try {
echo
inverse(0) . "\n";
} catch (
Exception $e) {
echo
'Excepción capturada: ', $e->getMessage(), "\n";
} finally {
echo
"Segundo finally.\n";
}

// Continuar ejecución
echo 'Hola Mundo\n';
?>

El resultado del ejemplo sería:

0.2
Primer finally.
Excepción capturada: División por cero.
Segundo finally.
Hola Mundo

Ejemplo #4 Interaction between the finally block and return

<?php

function test() {
try {
throw new
Exception('foo');
} catch (
Exception $e) {
return
'catch';
} finally {
return
'finally';
}
}

echo
test();
?>

El resultado del ejemplo sería:

finally

Ejemplo #5 Excepciones anidadas

<?php

class MiExcepción extends Exception { }

class
Prueba {
public function
probar() {
try {
try {
throw new
MiExcepción('foo!');
} catch (
MiExcepción $e) {
// relanzarla
throw $e;
}
} catch (
Exception $e) {
var_dump($e->getMessage());
}
}
}

$foo = new Prueba;
$foo->probar();

?>

El resultado del ejemplo sería:

string(4) "foo!"

Ejemplo #6 Multi catch exception handling

<?php

class MyException extends Exception { }

class
MyOtherException extends Exception { }

class
Test {
public function
testing() {
try {
throw new
MyException();
} catch (
MyException | MyOtherException $e) {
var_dump(get_class($e));
}
}
}

$foo = new Test;
$foo->testing();

?>

El resultado del ejemplo sería:

string(11) "MyException"

Ejemplo #7 Omitting the caught variable

Only permitted in PHP 8.0.0 and later.

<?php

class SpecificException extends Exception {}

function
test() {
throw new
SpecificException('Oopsie');
}

try {
test();
} catch (
SpecificException) {
print
"A SpecificException was thrown, but we don't care about the details.";
}
?>

Ejemplo #8 Throw as an expression

Only permitted in PHP 8.0.0 and later.

<?php

function test() {
do_something_risky() or throw new Exception('It did not work');
}

try {
test();
} catch (
Exception $e) {
print
$e->getMessage();
}
?>