Capítulo 15. Manejando errores

Existen diferentes tipos de errores y advertencias en PHP. Son los siguientes:

Tabla 15-1. Tipos de error PHP

ValorConstanteDescripciónNota
1E_ERRORerrores fatales en tiempo de ejecución 
2E_WARNINGadvertencias en tiempo de ejecución (no errores fatales) 
4E_PARSEerrores fatales en tiempo de compilación 
8E_NOTICEavisos en tiempo de ejecución (no tan importante como una advertencia) 
16E_CORE_ERRORerrores fatales que ocurren durante el proceso inicial de arranque de PHPSolo en PHP 4
32E_CORE_WARNINGadvertencias fatales que ocurren durante el proceso inicial de arranque de PHPSolo en PHP 4
64E_COMPILE_ERRORerrores fatales en tiempo de compilaciónsolo en PHP 4
128E_COMPILE_WARNINGadvertencias en tiempo de compilación (no errores fatales)Solo en PHP 4
256E_USER_ERRORmensaje de error generado por el usuarioSolo en PHP 4
512E_USER_WARNINGmensaje de advertencia generado por el usuariosolo en PHP 4
1024E_USER_NOTICE mensaje de aviso generado por el usuarioSolo en PHP 4
 E_ALLtodos los anteriores, all of the above, según lo soportado 

Los valores indicados arriba (tanto num$eacute;ricos como simbólicos) son usados para crear una máscara de bits (bitmask) que especifica de los errores que hay que informar. Podeis usar los operadores bitwise para combinar estos valores ó aplicar una máscara a ciertos tipos de errores. Tener en cuenta que que solamente '|', '~', '!', y '&' seran interpretados dentro de php.ini y que ningún operador bitwise será interpretado dentro de php3.ini.

En PHP 4, el valor por defecto de error_reporting es E_ALL & ~E_NOTICE, esto siginifica que todos los errores y advertencias que no pertenecen al nivel E_NOTICE, serán presentados cuando ocurran. En PHP 3, el valor por defecto es (E_ERROR | E_WARNING | E_PARSE), teniendo el mismo significado. Tener en cuenta que al no soportar constantes en el fichero de configuración de PHP php3.ini, el valor de error_reporting debe ser numérico, por lo tanto es 7.

La configuración inicial puede cambiarse, en el fichero ini con la directiva error_reporting, en el fichero httpd.conf de Apache con la directiva php_error_reporting (php3_error_reporting en PHP 3) y finalmente en tiempo de ejecución desde el script PHP que se este ejecutando, usando la función error_reporting().

Aviso

Cuando actualiceis código o servidores de PHP 3 a PHP 4, deberiais comprobar los valores y llamadas a error_reporting() para no deshabilitar los nuevos tipos de mensajes de error, especialmente E_COMPILE_ERROR. Si esto ocurriese podriais obtener documentos vacios sin ningún tipo de mensaje de error ó donde buscar el fallo.

Todas las expresioness PHP pueden también ser llamadas con el prefijo "@", el cual desactiva el aviso de errores para esa expresión en particular. Si ocurre un error en una expresión en tal situación y la característica track_errors está habilitada, podrás encontrar el mensaje de error en la variable global $php_errormsg.

Nota: El operador de control de errores @ no desactivará mensajes producidos por errores en el parseador.

Aviso

Actualmente el operador de control de errores @ incluso desactivará mensajes producidos por errores críticos que terminarán la ejecución del script. Entre otras cosas, esto significa que si utilizais @ para suprimir mensajes de error de alguna función, tanto si no está disponible como si contiene algún error, el script quedará interumpido sin ningún tipo de indicación de porque.

A continuación tenemos un ejemplo de como manejar errores en PHP. Definimos una función de manejo de errores, la cual registra el error en un fichero (usando el formato XML) y manda un e-mail al programador si un error crítico ocurre.

Ejemplo 15-1. Usando el manejo de errores en un script

<?php
// Los errores los manejamos nosotros
error_reporting(0);

// funcion de manejos de errores definida por el usuario
function userErrorHandler ($errno, $errmsg, $filename, $linenum, $vars) {
    // timestamp for the error entry
    $dt = date("Y-m-d H:i:s (T)");

    // Define una array con los valores de errores
    // en realidad solamente deberiamos de tener
    // en cuenta los valores 2,8,256,512 y 1024

    $errortype = array (
                1   =>  "Error",
                2   =>  "Warning",
                4   =>  "Parsing Error",
                8   =>  "Notice",
                16  =>  "Core Error",
                32  =>  "Core Warning",
                64  =>  "Compile Error",
                128 =>  "Compile Warning",
                256 =>  "User Error",
                512 =>  "User Warning",
                1024=>  "User Notice"
                );

    // errores a tener en cuenta
    $user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);
    
    $err = "<errorentry>\n";
    $err .= "\t<datetime>".$dt."</datetime>\n";
    $err .= "\t<errornum>".$errno."</errornum>\n";
    $err .= "\t<errortype>".$errortype[$errno]."</errortype>\n";
    $err .= "\t<errormsg>".$errmsg."</errormsg>\n";
    $err .= "\t<scriptname>".$filename."</scriptname>\n";
    $err .= "\t<scriptlinenum>".$linenum."</scriptlinenum>\n";

    if (in_array($errno, $user_errors))
        $err .= "\t<vartrace>".wddx_serialize_value($vars,"Variables")."</vartrace>\n";
    $err .= "</errorentry>\n\n";
    
    // Para comprobar
    // echo $err;

    // grabar en el fichero de errores y mandar un e-mail si ocurre un error critico de usuario
    error_log($err, 3, "/usr/local/php4/error.log");
    if ($errno == E_USER_ERROR)
        mail("phpdev@example.com","Critical User Error",$err);
}


function distance ($vect1, $vect2) {
    if (!is_array($vect1) || !is_array($vect2)) {
        trigger_error("Incorrect parameters, arrays expected", E_USER_ERROR);
        return NULL;
    }

    if (count($vect1) != count($vect2)) {
        trigger_error("Vectors need to be of the same size", E_USER_ERROR);
        return NULL;
    }

    for ($i=0; $i<count($vect1); $i++) {
        $c1 = $vect1[$i]; $c2 = $vect2[$i];
        $d = 0.0;
        if (!is_numeric($c1)) {
            trigger_error("Coordinate $i in vector 1 is not a number, using zero", 
                            E_USER_WARNING);
            $c1 = 0.0;
        }
        if (!is_numeric($c2)) {
            trigger_error("Coordinate $i in vector 2 is not a number, using zero", 
                            E_USER_WARNING);
            $c2 = 0.0;
        }
        $d += $c2*$c2 - $c1*$c1;
    }
    return sqrt($d);
}

$old_error_handler = set_error_handler("userErrorHandler");

//constante no definida, genera una advertencia
$t = I_AM_NOT_DEFINED;

// definimos algunos vectores
$a = array(2,3,"foo");
$b = array(5.5, 4.3, -1.6);
$c = array (1,-3);

// genera un error de usuario
$t1 = distance($c,$b)."\n";

// genera otro error de usuario
$t2 = distance($b,"i am not an array")."\n";

// genera una advertencia
$t3 = distance($a,$b)."\n";

?>
Este es un ejemplo simple que muestra como utilizar las funciones de manejo de errores y registro.

Consultar tambien error_reporting(), error_log(), set_error_handler(), restore_error_handler(), trigger_error(), user_error()