En cualquier aplicación que desee realizarse, el control de errores es primordial. PHP5 nos ofrece una útil función para ello que es set_error_handler(), esta función nos permitirá enmascarar los errores para podrá crear un log propio de los errores (en caso de no tener acceso al servidor como administrador) o bien como algunos programadores amigos míos dirían “no mostrar los warning y notice del sistema”; aunque es una practica que no promuevo, a veces es necesaria.
La clase que mostrare es para poder manejar los errores y poder mostrarlos a voluntad, así como crear logs cuando lo creamos necesario.
class error{var $_contexto; var $codigo;function error($contexto,$error){ $this->_contexto =& $contexto; $GLOBALS['_OBJETO_CONTEXTO'] =& $this->_contexto; $this->activo($error); }
Al crear la clase, capturaremos el contexto (que sera el error reportado por PHP) para luego asignarlo a una variable propia de la clase para manejar la mas adelante. Así mismo crearemos una variable global con el contexto y verificaremos con una función propietaria si la clase esta activa o no para mostrar errores. La variable $error es una variable definida por el usuario que nos indicara si mostrara los errores o los ocultara.
function activo(){
switch(func_num_args()){
case 1: $this->_activo = func_get_arg(0); $this->iniciar(); break;
case 0: return $this->_activo;
}
}
Si mostramos los errores, comenzamos con la función iniciar(). Esta función nos permitirá crear con la variable $contexto (donde esta el error) un manejador de errores propio. Capturara el error y lo enviara a otra clase separado por NUMERO de error predefinido por PHP, MENSAJE del error, ARCHIVO donde se produjo el error, LINEA donde se produjo el error en el archivo y por ultimo el MENSAJE o CONTEXTO del error. Con estas variables tipo String separadas podremos crear mas adelante un estilo para mostrarlas.
function iniciar(){if(!function_exists('adm_error')){ function adm_error($numero, $mensaje, $archivo, $linea, $contexto, $retorna=false){ $objContexto =& $GLOBALS['_OBJETO_CONTEXTO']; $objContexto->inicializar($numero, $mensaje, $archivo, $linea, $contexto); if($retorna) return $objContexto->leer(); else print $objContexto->leer(); } }if(!function_exists('errorFatal')){ function errorFatal($buffer){ $buffer_temporal = $buffer; $texto = strip_tags($buffer_temporal); if(preg_match('/Parse error X: (.+) in (.+)? on line (\d+)/', $texto, $c)) return adm_error(E_USER_ERROR, $c[1], $c[2], $c[3], "", true); if(preg_match('/Fatal error X: (.+) in (.+)? on line (\d+)/', $texto, $c)) return adm_error(E_USER_ERROR, $c[1], $c[2], $c[3], "", true); return $buffer; } }if( $this->activo() ){ error_reporting(0); ob_start('errorFatal'); set_error_handler('adm_error'); } else error_reporting(0); } function exception_handler($exception) { echo "Uncaught exception: " , $exception->getMessage(), "\n"; }} // Aqui cerramos la clase error
Ahora crearemos la clase Contexto, que resibira los parámetros de la clase Error y los mostrara en un formato predefinido, ademas de crear un LOG en archivos de texto separados por tipo de errores. _ERRORDETALLE y _LOGS son variables globales definidas por el usuario, esto nos ayuda no mostrar los detalles del error (como archivo y codigo) una vez que este en producción el sistema, así mismo a controlar la creación de los logs.
class Contexto
{
var $_numero = "";
var $_mensaje = "";
var $_Estilo = "";
var $_Imagen = "";
var $_lineas = 5;
var $_noticiaEstilo = "style='font-style:italic;font-size:11px;font-family:Arial, Helvetica, sans-serif;margin:5px;color:#000000;padding: 5px;width: 90%;display:block;background-color:#FFFFCC;border: solid 1px #CFCFCF;'";
var $_noticiaImagen = "<img src='noticia.gif' align='left' hspace='5'>";
var $_alertaEstilo = "style='font-style:italic;font-size:11px;font-family:Arial, Helvetica, sans-serif;margin:5px;color:#000000;padding: 5px;width: 90%;display:block;background-color:#FDDAD8;border: solid 1px #CFCFCF;'";
var $_alertaImagen = "<img src='alerta.gif' align='left' hspace='5'>";
var $_codigoEstilo = "style='width: 90%;background-color: #F1F1F1;margin: 5px;border: solid 1px #CFCFCF;display:block;'";
function inicializar($numero, $mensaje, $archivo, $linea, $contexto)
{
$errorlevels = array(2048=>'Runtime Notice',2047=>'Runtime Notice',1024=>'User Notice',512=>'User Warning',256=>'User Error',128=>'Compile Warning',64=>'Compile Error',32=>'Core Warning',16=>'Core Error',8=>'Notice',4=>'Parsing Error',2=>'Warning',1=>'Error');
$this->_Estilo=(($numero==2048)or($numero==2047)or($numero==1024)or($numero==8))?$this->_noticiaEstilo:$this->_alertaEstilo;
$this->_Imagen=(($numero==2048)or($numero==2047)or($numero==1024)or($numero==8))?str_replace('HOSTZOD',_HOSTZOD,$this->_noticiaImagen):str_replace('HOSTZOD',_HOSTZOD,$this->_alertaImagen);
$this->_Imagen=(_ERRORDETALLE)?$this->_Imagen:substr($this->_Imagen,0,(strlen($this->_Imagen)-1)).' width="23" height="21" style="position:relative;top:-3px">';
$this->_mensaje = "<pre><div ".$this->_Estilo.">".$this->_Imagen."<b>".$errorlevels[$numero].":</b> ";
$this->_mensaje.=(_ERRORDETALLE)?"$mensaje<br><b>Archivo:</b> ".substr($archivo,strrpos($archivo, "\\")+1,strlen($archivo))."<br><b>Línea:</b> $linea<br></div><div ".$this->_codigoEstilo.">".$this->obtenerContexto($archivo, (int) $linea)."</div></pre>":date("ymdHis")."</div></pre>";
if(_LOGS){error_log(date("YmdHis")."|".$_SERVER['HTTP_X_FORWARDED_FOR']."|$mensaje|".substr($archivo,strrpos($archivo, "\\")+1,strlen($archivo))."|$linea\r\n",3,"error".str_replace(" ", "",$errorlevels[$numero]).".log");}
}
function leer(){
return $this->_mensaje;
}
function obtenerContexto($archivo, $linea){
if (!file_exists($archivo)) {
return "El contexto no puede mostrarse - ($archivo) no existe";
} elseif ((!is_int($linea)) OR ($linea <= 0)) {
return "El contexto no puede mostrarse - ($linea) es un número inválido de linea";
} else {
$codigo = file( $archivo);
$lineas = count($codigo);
$inicio = $linea - $this->_lineas;
$fin = $linea + $this->_lineas;
if ($inicio < 0) $inicio = 0;
if ($fin >= $lineas) $fin = $lineas;
$largo_fin= strlen($fin) + 2;
for ($i = $inicio; $i < $fin; $i++){
$color=($i==$linea-1?"red; font-weight:bold":"black");
$salida[] = "<span style='color: $color'>".($i+1).str_repeat(" ", $largo_fin - strlen($i)).htmlentities($codigo[$i]).'</span>';
}
return trim(join("", $salida));
}
}
}
Para modificar el estilo solo debe modificar las variables $_noticiaEstilo, $_noticiaImagen, $_alertaEstilo y $_alertaImagen. Dejo las que yo suelo usar porque me parecen de buen ver. Los archivos de logs se ubicaran en la misma carpeta. Creo que en si la clase Contexto no necesita mucha explicación, así que me despido esperando que sea de ayuda. Para usar la función simplemente incluimos el archivo y usamos la sentencia: $error = new error( new Contexto );
Tags: error, logs, manejo de errores, PHP
jajaja los que ocultan los warning deberian de morir!!!…. hervidos en aceite caliente
salu2
Ddaz