Saltar al contenido principal

Excepciones

La gestión de excepciones forma parte desde PHP 5. Su funcionamiento es similar a Java, haciendo uso de un bloque try / catch / finally. Si detectamos una situación anómala y queremos lanzar una excepción, deberemos realizar throw new Exception (adjuntando el mensaje que lo ha provocado).

<?php
try {
if ($divisor == 0) {
throw new Exception("División por cero.");
}
$resultado = $dividendo / $divisor;
} catch (Exception $e) {
echo "Se ha producido el siguiente error: ".$e->getMessage();
}

La clase Exception es la clase padre de todas las excepciones. Su constructor recibe mensaje[,codigoError][,excepcionPrevia].

A partir de un objeto Exception, podemos acceder a los métodos getMessage()y getCode() para obtener el mensaje y el código de error de la excepción capturada.

El propio lenguaje ofrece un conjunto de excepciones ya definidas, las cuales podemos capturar (y lanzar desde PHP 7). Se recomienda su consulta en la documentación oficial.

Creando excepciones

Para crear una excepción, la forma más corta es crear una clase que únicamente herede de Exception.

<?php
class HolaExcepcion extends Exception {}

Si queremos, y es recomendable dependiendo de los requisitos, podemos sobrecargar los métodos mágicos, por ejemplo, sobrecargando el constructor y llamando al constructor del padre, o rescribir el método __toString para cambiar su mensaje:

<?php
class MiExcepcion extends Exception {
public function __construct($msj, $codigo = 0, Exception $previa = null) {
// código propio
parent::__construct($msj, $codigo, $previa);
}
public function __toString() {
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
}
public function miFuncion() {
echo "Una función personalizada para este tipo de excepción\n";
}
}

Si definimos una excepción de aplicación dentro de un namespace, cuando referenciemos a Exception, deberemos referenciarla mediante su nombre totalmente cualificado (\Exception), o utilizando use:

Mediante nombre totalmente cualificado
<?php
namespace \Dwes\Ejemplos;

class AppExcepcion extends \Exception {}
Mediante use
<?php
namespace \Dwes\Ejemplos;

use Exception;

class AppExcepcion extends Exception {}

Excepciones múltiples

Se pueden usar excepciones múltiples para comprobar diferentes condiciones. A la hora de capturarlas, se hace de más específica a más general.

<?php
$email = "ejemplo@ejemplo.com";
try {
// Comprueba si el email es válido
if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
throw new MiExcepcion($email);
}
// Comprueba la palabra ejemplo en la dirección email
if(strpos($email, "ejemplo") !== FALSE) {
throw new Exception("$email es un email de ejemplo no válido");
}
} catch (MiExcepcion $e) {
echo $e->miFuncion();
} catch(Exception $e) {
echo $e->getMessage();
}

Si en el mismo catch queremos capturar varias excepciones, hemos de utilizar el operador |:

<?php
class MainException extends Exception {}
class SubException extends MainException {}

try {
throw new SubException("Lanzada SubException");
} catch (MainException | SubException $e ) {
echo "Capturada Exception " . $e->getMessage();
}

Desde PHP 7, existe el tipo Throwable, el cual es un interfaz que implementan tanto los errores como las excepciones, y nos permite capturar los dos tipos a la vez:

<?php
try {
// tu codigo
} catch (Throwable $e) {
echo 'Forma de capturar errores y excepciones a la vez';
}

Si sólo queremos capturar los errores fatales, podemos hacer uso de la clase Error:

<?php
try {
// Genera una notificación que no se captura
echo $variableNoAsignada;
// Error fatal que se captura
funcionQueNoExiste();
} catch (Error $e) {
echo "Error capturado: " . $e->getMessage();
}

Relanzar excepciones

En las aplicaciones reales, es muy común capturar una excepción de sistema y lanzar una de aplicación que hemos definido nostros. También podemos lanzar las excepciones sin necesidad de estar dentro de un try/catch.

<?php
class AppException extends Exception {}

try {
// Código de negocio que falla
} catch (Exception $e) {
throw new AppException("AppException: ".$e->getMessage(), $e->getCode(), $e);
}