Bloque catch

Un bloque **catch** tiene el siguiente aspecto:

catch (typehint exception)
{
   //código que queremos ejecutar al capturar la excepción
}

Usaremos la palabra reservada catch seguida de un argumento de diferente tipo. La determinación del tipo de argumento es lo que define si se ejecuta o no el código que hay dentro del bloque catch. Es lo que vimos anteriormente como "sugerencia de tipos" (typehint).

Cuando se genera una excepción, las condiciones de excepción se comprueban en el orden que aparecen, hasta que aparece una sentencia catch que coincide con el tipo del argumento activado en la excepción. Cuando esto sucede, el control pasa al bloque catch y el argumento enviado en la excepción se usa como argumento para ese bloque.

Vamos a ver un ejemplo completo con código PHP fuera del bloque try-catch, un bloque try que realiza una conexión a una base datos e imprime por pantalla el número de filas de la tabla libros y finalmente un bloquye catch que captura la excepción y muestra un mensaje de error.

Veamos un ejemplo completo:

<?php
echo "ANTES DEL BLOQUE try-catch";
echo "<hr>";

try
{
   if (mysql_connect('localhost', 'user', '123456', 'uazon' ) === false)
     throw new Exception('Error de conexion con la base de datos', 42);
   mysql_query("SELECT * FROM libros");
   echo "Numero de libros: " . mysql_numrows();
}
catch (Exception $e) {
   echo 'Excepcion ' . $e->getCode() . ': ' . $e->getMessage() .
      ' en la linea ' . $e->getLine() .
      ' del fichero ' . $e->getFile() . '<br />';
   exit;
}
echo "<hr>";
echo "DESPUES DEL BLOQUE CATCH";
?>

Este es un ejemplo sencillo donde mostramos el número de libros dados de alta en la base de datos del proyecto. Antes del bloque try-catch tenemos código PHP que siempre se ejecutará. Dentro del bloque try tenemos instrucciones susceptibles a que provoquen un error y que incluso, dicho error, sea arrastrado hasta el final del script o que dicho error provoque un error fatal finalizando la ejecución del mismo. Dentro del bloque try-catch intentamos realizar una conexión con la base de datos, ejecutamos una consulta y posteriormente mostramos el número de libros encontrados.

Vamos a analizar el resultado que nos proporciona la ejecución de dicho script. Resultado:

ANTES DEL BLOQUE try-catch
________________________________________
Warning: mysql_connect() [function.mysql-connect.php]: Access
   denied for user 'user'@'localhost' (using password: YES) in
   C:\wamp\www\sesion09\ejemplo.php on line 6
Excepción 42: Error de conexión con la base de datos en la línea 7
   del fichero C:\wamp\www\sesion09\ejemplo.php

Ejemplo de lanzamiento y captura de una excepción

Como vemos, después de la etiqueta HTML `


` tenemos el código del bloque try-catch. En un primer vistazo destacamos el **Warning** que lanza la función "mysql_connect()" que nos muestra el mensaje de error que le ha devuelto MySQL (acceso denegado a localhost al usuario 'user' con password '123456'). En el tema de conexión a bases de datos MySQL veremos con más detenimiento esas funciones.

¿Por qué aparece ese mensaje de error? Porque estamos en un entorno de desarrollo y lo recomendable es activar el nivel de aviso de errores a lo máximo posible como es nuestro caso. En un entorno de producción, deshabilitaríamos los errores y seríamos nosotros los encargados de capturar y controlar esos errores.

Ya vimos en sesiones anteriores que en PHP existe un operador que cancela cualquier mensaje de error que se genere en la ejecución de instrucciones. Ese operador es la '@'.

Vamos a anteponer dicho operador delante de las instrucción 'mysql_connect()' y volver a ejecutar el código del anterior ejemplo:

<?php
echo "ANTES DEL BLOQUE try-catch";
echo "<hr>";

try
{
   if (@mysql_connect('localhost', 'user', '123456', 'uazon' ) === false)
          throw new Exception('Error de conexión con la base de datos', 42);

       mysql_query( );
       echo . mysql_numrows();
}
catch (Exception $e)
{
   echo 'Excepción ' . $e->getCode() . ': ' . $e->getMessage() .
      ' en la línea ' . $e->getLine() .
      ' del fichero ' . $e->getFile() . '<br />';
   exit;
}
echo "<hr>";
echo "DESPUES DEL BLOQUE CATCH";
?>

El resultado es el siguiente:

ANTES DEL BLOQUE try-catch
________________________________________
Excepción 42: Error de conexión con la base de datos en la línea 6
   del fichero C:\wamp\www\sesion09\ejemplo.php

Como vemos, no aparece ningún mensaje de advertencia y se ha capturado la excepción el resultado correctamente. Esta práctica no es aconsejable pues desactivamos los posibles errores que puede generar PHP. Lo ideal es que seamos nosotros los que configuremos el nivel de error adecuado al entorno en el que la aplicación se encuentre desplegada.

¿Qué pasaría si no hubiéramos generado la excepción? Vamos a verlo. Imaginemos que MySQL cae y nosotros ejecutamos el script sin capturar la excepción.

Ejemplo anterior pero sin lanzar la excepción.

<?php
echo "ANTES DEL BLOQUE try-catch";
echo "<hr>";

try
{
   mysql_connect('localhost', 'user', '123456');

   mysql_query( );

   echo . mysql_numrows();

}
catch (Exception $e)
{
   echo 'Excepción ' . $e->getCode() . ': ' . $e->getMessage() .
      ' en la línea ' . $e->getLine() .
      ' del fichero ' . $e->getFile() . '<br />';
   exit;
}
echo "<hr>";
echo "DESPUES DEL BLOQUE CATCH";
?>

Resultado

ANTES DEL BLOQUE try-catch
________________________________________
Warning: mysql_connect() [function.mysql-connect.php]: Can't
   connect to MySQL server on 'localhost' (10061) in
   C:\wamp\www\sesion09\ejemplo.php on line 7
Warning: mysql_query() [function.mysql-query.php]: Can't connect
   to MySQL server on 'localhost' (10061) in
   C:\wamp\www\sesion09\ejemplo.php on line 9
Warning: mysql_query() [function.mysql-query.php]: A link to the
   server could not be established in C:\wamp\www\sesion09\ejemplo.php
   on line 9
Warning: Wrong parameter count for mysql_numrows() in
   C:\wamp\www\sesion09\ejemplo.php on line 11
Número de libros:
________________________________________
DESPUÉS DEL BLOQUE CATCH

Como vemos en el ejemplo, el bloque catch no se ejecuta y se muestran en pantalla todas las advertencias (Warning) que lanzan automáticamente las funciones propias de MySQL. A parte de lo poco profesional que queda mostrar esta secuencia de advertencias al usuario (con números de línea y rutas de ficheros) dicho error se ha ido trasladando hacia las siguientes instrucciones del script provocando una cadena de errores. Tampoco hemos hablado de los problemas de seguridad que implica mostrar rutas de ficheros por pantalla y mensajes de error propios de MySQL.

Como vimos en una sesión anterior, en el fichero **php.ini** disponemos de varios niveles de error. Como estamos en un entorno de desarrollo nos interesa que se muestren todos los errores posibles.

Se puede crear una clase para la gestión de cierto tipo de excepciones. Recordemos que al generarse una excepción por medio de throw podemos crear un objeto de cualquier tipo de clase y que la sentencia catch detecte el tipo de dato de la excepción para saber si es ella quien debe tratar la excepción o si debe gestionar una excepción cuando existe coincidencia en el tipo de argumento (por ejemplo es de la clase Exception); después de ejecutadas estas instrucciones del bloque catch de la clase coincidente, la secuencia de ejecución sigue con la primera sentencia posterior al último bloque catch.

Si dentro de los bloques catch no aparece ninguna que sea coincidente al objeto, entonces el programa termina sin producir ningún tratamiento especial a la excepción.

Dentro de un bloque catch podemos crear nuevas excepciones y ésta será capturada por otro gestor de excepciones.

results matching ""

    No results matching ""