PHP tiene un modelo de excepciones similar al de otros lenguajes de programación.
Una excepción puede ser lanzada ("throw
n"), y atrapada ("catch
ed") 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 ("throw
n") (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.
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
.
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');
?>
La Biblioteca Estándar de PHP (SPL) proporciona una buena cantidad de excepciones integradas.
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();
}
?>