PHP Manejo de excepciones


Las excepciones se utilizan para cambiar el flujo normal de un script cuando ocurre un error especificado.


¿Qué es una excepción?

PHP 5 proporciona un nuevo método de manejo de errores orientado a objetos.

El manejo de excepciones se utiliza para cambiar el flujo normal del script cuando ocurre una situación de error (excepción) especificada. Esta situación se llama excepción.

Cuando se desencadena una excepción, normalmente ocurre lo siguiente:

  • Se guarda el estado actual del código
  • La ejecución del código se cambia a una función de manejador de excepciones predefinida (personalizada)
  • Según la situación, el manejador puede reiniciar la ejecución del código desde el estado guardado, terminar la ejecución del script, o continuar la ejecución del script desde otra ubicación en el código.

Mostraremos diferentes métodos de manejo de errores:

  • Uso básico de excepciones
  • Crear un manejador de excepciones personalizado
  • Múltiples excepciones
  • Relanzar excepciones
  • Establecer un manejador de excepciones de nivel superior

Nota:Las excepciones solo deben usarse en condiciones de error, y no deben usarse para saltar a otra ubicación del código en un punto específico.


Uso básico de excepciones

Cuando se lanza una excepción, el código posterior no continúa ejecutándose; PHP intenta buscar un bloque "catch" coincidente.

Si la excepción no se captura y no se utiliza set_exception_handler() para manejarla adecuadamente, entonces ocurrirá un error grave (error fatal) y se mostrará un mensaje de error "Uncaught Exception" (excepción no capturada).

Intentemos lanzar una excepción sin capturarla:

<?php //Crear una función con manejo de excepciones function checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true; } //Desencadenar la excepción checkNum(2); ?>

El código anterior producirá un error similar a este:

Fatal error: Uncaught exception 'Exception' with message 'Value must be 1 or below' in /www/ejemplo/test/test.php:7 Stack trace: #0 /www/ejemplo/test/test.php(13): checkNum(2) #1 {main} thrown in /www/ejemplo/test/test.php on line 7

Try, throw y catch

Para evitar el error que aparece en el ejemplo anterior, necesitamos crear el código adecuado para manejar las excepciones.

El código adecuado para el manejo de excepciones debe incluir:

  1. Try: la función que usa excepciones debe estar dentro de un bloque "try". Si no se desencadena una excepción, el código continuará ejecutándose con normalidad. Pero si se desencadena una excepción, se lanzará una excepción.
  2. Throw: aquí se especifica cómo desencadenar la excepción. Cada "throw" debe corresponder al menos a un "catch".
  3. Catch: el bloque "catch" captura la excepción y crea un objeto que contiene la información de la excepción.

Vamos a desencadenar una excepción:

<?php //Crear una función con manejo de excepciones function checkNum($number) { if($number>1) { throw new Exception("El valor de la variable debe ser menor o igual a 1"); } return true; } //Desencadenar la excepción en el bloque try try { checkNum(2); //Si se lanza una excepción, el siguiente texto no se mostrará echo 'Si se muestra este contenido, significa que la variable $number'; } //Capturar la excepción catch(Exception $e) { echo 'Message: ' .$e->getMessage(); } ?>

El código anterior producirá un error similar a este:

Message: 变量值必须小于等于 1

Explicación del ejemplo:

El código anterior lanzó una excepción y la capturó:

  1. Se crea la función checkNum(). Esta comprueba si el número es mayor que 1. Si es así, lanza una excepción.
  2. Se llama a la función checkNum() dentro del bloque "try".
  3. Se lanza la excepción en la función checkNum().
  4. El bloque "catch" recibe la excepción y crea un objeto ($e) que contiene la información de la excepción.
  5. Al llamar a $e->getMessage() desde este objeto exception, se muestra el mensaje de error de la excepción.

Sin embargo, para seguir el principio de "cada throw debe corresponder a un catch", se puede establecer un manejador de excepciones de nivel superior para manejar los errores omitidos.


Crear una clase Exception personalizada

Crear un manejador de excepciones personalizado es muy simple. Simplemente creamos una clase especializada cuyas funciones pueden llamarse cuando ocurre una excepción en PHP. Esta clase debe ser una extensión de la clase exception.

Esta clase personalizada customException hereda todas las propiedades de la clase exception de PHP, y puede agregarle funciones personalizadas.

Comenzamos a crear la clase customException:

<?php class customException extends Exception { public function errorMessage() { //Mensaje de error $errorMsg = 'Número de línea del error'.$this->getLine().' in '.$this->getFile() .': <b>'.$this->getMessage().'</b> no es una dirección de E-Mail válida'; return $errorMsg; } } $email = "[email protected]"; try { //Verificar el correo electrónico if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //Si es una dirección de correo electrónico no válida, lanzar una excepción throw new customException($email); } } catch (customException $e) { //display custom message echo $e->errorMessage(); } ?>

Esta nueva clase es una copia de la antigua clase exception, más la función errorMessage(). Precisamente porque es una copia de la clase antigua, hereda las propiedades y métodos de la clase antigua; podemos usar métodos de la clase exception, como getLine(), getFile() y getMessage().

Explicación del ejemplo:

El código anterior lanzó una excepción y la capturó mediante una clase exception personalizada:

  1. La clase customException() se creó como una extensión de la antigua clase exception. De esta manera hereda todas las propiedades y métodos de la antigua clase exception.
  2. Se crea la función errorMessage(). Si la dirección de e-mail no es válida, esta función devuelve un mensaje de error.
  3. Se asigna a la variable $email una cadena de dirección de e-mail no válida.
  4. Se ejecuta el bloque "try"; como la dirección de e-mail no es válida, se lanza una excepción.
  5. El bloque "catch" captura la excepción y muestra el mensaje de error.

Múltiples excepciones

Se pueden usar múltiples excepciones para un script, para detectar varias situaciones.

Se pueden usar múltiples bloques if..else, o un bloque switch, o anidar múltiples excepciones. Estas excepciones pueden usar diferentes clases exception y devolver diferentes mensajes de error:

<?php class customException extends Exception { public function errorMessage() { //Mensaje de error $errorMsg = 'Número de línea del error'.$this->getLine().' in '.$this->getFile() .': <b>'.$this->getMessage().'</b> no es una dirección de E-Mail válida'; return $errorMsg; } } $email = "[email protected]"; try { //Verificar el correo electrónico if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //Si es una dirección de correo electrónico no válida, lanzar una excepción throw new customException($email); } //Comprobar si "example" está en la dirección de correo electrónico if(strpos($email, "example") !== FALSE) { throw new Exception("$emailEs un correo de example"); } } catch (customException $e) { echo $e->errorMessage(); } catch(Exception $e) { echo $e->getMessage(); } ?>

Explicación del ejemplo:

El código anterior prueba dos condiciones; si alguna de ellas no se cumple, lanza una excepción:

  1. La clase customException() se creó como una extensión de la antigua clase exception. Así hereda todas las propiedades y métodos de la antigua clase exception.
  2. Se crea la función errorMessage(). Si la dirección de e-mail no es válida, la función devuelve un mensaje de error.
  3. Se asigna a la variable $email una cadena que es una dirección de e-mail válida, pero que contiene la cadena "example".
  4. Se ejecuta el bloque "try"; en la primera condición no se lanza una excepción.
  5. Debido a que el e-mail contiene la cadena "example", la segunda condición desencadena una excepción.
  6. El bloque "catch" captura la excepción y muestra el mensaje de error adecuado.

Si la clase customException lanza una excepción, pero no se captura customException, solo se captura la excepción base, entonces la excepción se maneja allí.


Relanzar excepciones

A veces, cuando se lanza una excepción, es posible que desee manejarla de una manera diferente a la estándar. Puede volver a lanzar la excepción dentro de un bloque "catch".

El script debe ocultar los errores del sistema al usuario. Para el programador, los errores del sistema pueden ser importantes, pero al usuario no le interesan. Para facilitar su uso al usuario, puede volver a lanzar una excepción con un mensaje más amigable para el usuario:

<?php class customException extends Exception { public function errorMessage() { //Mensaje de error $errorMsg = $this->getMessage().'No es una dirección de E-Mail válida.'; return $errorMsg; } } $email = "[email protected]"; try { try { //Comprobar si "example" está en la dirección de correo electrónico if(strpos($email, "example") !== FALSE) { //Si es una dirección de correo electrónico no válida, lanzar una excepción throw new Exception($email); } } catch(Exception $e) { //Relanzar la excepción throw new customException($email); } } catch (customException $e) { //Mostrar mensaje personalizado echo $e->errorMessage(); } ?>

Explicación del ejemplo:

El código anterior comprueba si la dirección de correo contiene la cadena "example". Si la contiene, vuelve a lanzar la excepción:

  1. La clase customException() se creó como una extensión de la antigua clase exception. De esta manera, hereda todas las propiedades y métodos de la antigua clase exception.
  2. Crear la función errorMessage(). Si la dirección de correo electrónico no es válida, la función devuelve un mensaje de error.
  3. Establecer la variable $email a una cadena que sea una dirección de correo electrónico válida, pero que contenga la cadena "example".
  4. El bloque de código "try" contiene otro bloque "try", de modo que se puede volver a lanzar una excepción.
  5. Como el correo electrónico contiene la cadena "example", se dispara la excepción.
  6. El bloque "catch" captura la excepción y vuelve a lanzar "customException".
  7. Se captura "customException" y se muestra un mensaje de error.

Si la excepción no se captura en el bloque "try" actual, se buscará un bloque catch en un nivel superior.


Establecer un manejador de excepciones de nivel superior

La función set_exception_handler() puede establecer una función definida por el usuario que maneje todas las excepciones no capturadas.

<?php function myException($exception) { echo "<b>Exception:</b> " , $exception->getMessage(); } set_exception_handler('myException'); throw new Exception('Uncaught Exception occurred'); ?>

La salida del código anterior es la siguiente:

Exception: Uncaught Exception occurred

En el código anterior, no existe un bloque "catch", sino que se activa el manejador de excepciones de nivel superior. Se debe usar esta función para capturar todas las excepciones no capturadas.


Reglas de las excepciones

  • El código que requiere manejo de excepciones debe colocarse dentro de un bloque try, para poder capturar posibles excepciones.
  • Cada bloque try o throw debe tener al menos un bloque catch correspondiente.
  • El uso de múltiples bloques catch permite capturar diferentes tipos de excepciones.
  • Se puede lanzar (volver a lanzar) una excepción dentro de un bloque catch que se encuentre en un bloque try.

En resumen: si se lanza una excepción, debe capturarse.

Otras extensiones