Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

M4n0w4r

[Resolvido] Tratamento de Erros

Recommended Posts

*** NÃO SOU DONO DA VERDADE NEM DA PERFEIÇÃO POSSO ESTAR ERRADO OU ENGANADO ***

Olá galera, depois de meses com soluções complexas e confusas finalmente encontrei uma maneira fácil de se tratar todos os erros em PHP tanto no lado cliente quanto no lado servidor. Estou compartilhando com vocês pois não quero que mais um pobre ser humano passe a dor de cabeça que eu passei. Isso é apenas mais um script formado pela minha opnião, se vai ajudar você ou não depende da sua necessidade.

Eu antigamente por pouco conhecer dos recursos que o PHP oferece usava muito if/else para controle de erros, pura perda de tempo ! Um exemplo:

<?php
	function leArquivo ($arquivo) {
		if (is_writable ($arquivo)) {
			if ($tamanhoArquivo = filesize ($arquivo) !== 0) {
				if ($abre_ler = fopen ($arquivo, "r")) {
					if ($conteudo = fread ($abre_ler, filesize ($arquivo))) {
						if (fclose ($abre_ler)) {
							return $conteudo;
						}
						else {
							exit ("Não foi possível fechar o arquivo '$arquivo'");
						}
					}
					else {
						exit ("Não foi possível ler o arquivo '$arquivo'");
					}
				}
				else {
					exit ("Não foi possível abrir o arquivo '$arquivo'");
				}
			}
			else {
				exit ("O arquivo '$arquivo' está vazio");
			}
		}
		else {
			exit ("O arquivo '$arquivo' não existe ou não é escrevível");
		}
	}
?>

Doi meus olhos so de ver ! Isso mudou muito com o comando "or" e "exit":

<?php
	function leArquivo ($arquivo) {
		is_writable ($arquivo) or exit ("O arquivo '$arquivo' não existe ou não é escrevível");
		
		$tamanhoArquivo = filesize ($arquivo) !== 0 or exit ("O arquivo '$arquivo' está vazio");
		
		$abre_ler = fopen ($arquivo, "r") or exit ("Não foi possível abrir o arquivo '$arquivo'");
		
		$conteudo = fread ($abre_ler, filesize ($arquivo)) or exit ("Não foi possível ler o arquivo '$arquivo'");
		
		fclose ($abre_ler) or exit ("Não foi possível fechar o arquivo '$arquivo'");
	}
?>

Bem melhor ! Se ocorreu tudo certo com uma função, ok, o script segue em frente senão entra no "exit" que para toda a aplicação e imprime a mensagem.

Tanto o usuário quanto o programador vão ver o error e o usuário não pode saber que o arquivo "Fulano.php" não pôde ser lido, isso pode ser usado em ações maliciosas contra o sistema. A solução é entregar mensagens genêricas de desculpas, ae surge um outro problema, como eu (programador) posso solucionar essa confusão se eu não vou saber de nada ? Isso é solucionado com um log que guarda a linha e o nome do arquivo que ocorreu o problema.

<?php
	function erroFuncao () {
		$diretorio = "c:/logFuncao.txt" // Windows
		$mensagemUsuario = "Ocorreu um erro, desculpe-nos pelo transtorno, iremos resolvê-lo o mais rápido póssivel.";
		
		$debug = debug_backtrace () or exit ("Erro");
		
		$mensagemSistema = date ("d/m/y") . " as " . date ("G:i s") . "\n";
		$mensagemSistema .= "\tArquivo: \"" . $debug[0]["file"] . "\"\n";
		$mensagemSistema .= "\tLinha: \"" . $debug[0]["line"] . "\"\n\n";
		
		error_log ($mensagemSistema, 3, $diretorio) or exit ("Erro");
		
		exit ($mensagemUsuario);
	}
	
	is_writable ("meuArquivo.txt") or erroFuncao ();
?>

Explicação:
2ª linha: Diretório em que será guardado o log
3ª linha: Mensagem genérica de desculpa para o usuário
5ª linha: http://php.net/manual/en/function.debug-backtrace.php, essa função puxa um monte de informações do local de onde nossa função "erroFunção" foi chamada
7º até 9ª linha: Mensagem que ficará no log
11ª linha: http://br2.php.net/manual/en/function.error-log.php, função que gera o log.
13ª linha: Interrompe o script e mostra a mensagem pro usuário

E esses "exit ("Erro")" ? Bom, são possíveis erros que podem ocorrer numa função que trata erros ! Ae o único jeito de diferencia-las das outras mensagens é lhes
atribuindo caracteristicas únicas, nesse caso eu coloquei uma frase diferente da padrão.


Perfeito ? Não tão perfeito, em computação tudo é possível e cada pessoa possui uma necessidade diferente, por isso tentei fazer um script com três possibilidades

- A mensagem padrão de desculpas que já falamos
- Uma mensagem personalizada
- É mostrado para o usuário um número, esse mesmo número fica no log, assim o administrador busca no log aquele erro específico através do número que o usário informou (Intranet ou Extranet)

<?php
	function erroFuncao ($tiposMensagens = false) {
		is_string ($tiposMensagens) || is_bool ($tiposMensagens) or exit ("Erro Nº 0. Favor anotar o número e contactar o administrador.");

		$mensagemSistema = date ("d/m/y") . " as " . date ("G:i s") . "\n";
		
		if ($tiposMensagens === true) {
			// Identificador deve ser único, esse método não é confiavél pois pode existir duas requisições no mesmo intervaulo de tempo
			$identificador = mt_rand (2, mt_getrandmax ());
			
			$mensagemSistema = "Erro Nº " . $identificador . " de " . date ("d/m/y") . " as " . date ("G:i s") . "\n";
			$mensagemUsuario = "Erro Nº " . $identificador . ". Favor anotar o número e contactar o administrador";
		}
		else if ($tiposMensagens === false)
			$mensagemUsuario = "Ocorreu um erro, desculpe-nos pelo transtorno, iremos resolvê-lo o mais rápido póssivel.";
		else
			$mensagemUsuario = $tiposMensagens;
		
		$debug = debug_backtrace () or exit ("Erro Nº 1. Favor anotar o número e contactar o administrador.");
		
		$mensagemSistema .= "\tArquivo: \"" . $debug[0]["file"] . "\"\n";
		$mensagemSistema .= "\tLinha: \"" . $debug[0]["line"] . "\"\n\n";
		
		error_log ($mensagemSistema, 3, "c:/logFuncao.txt") or exit ("Erro Nº 2. Favor anotar o número e contactar o administrador.");
		
		exit (json_encode ($mensagemUsuario));
	}
?>

Explicação:
Se for passado uma "string" mostra essa string para o usuário, se for "true" mostra o número (identificador), se for "false" mostra a mensagem padrão de desculpas.

2ª linha: So é possível 3 parametros que mencionei acima, se o programador inserir alguma coisa diferente retorna um erro.
4ª linha: Primeira linha da mensagem do log (sistema)
6ª linha: Se quero mostrar um identificador substituo a primeira linha da mensagem do log

Pronto, na prática fica assim:
<?php
	// Padrão
	is_writable ("Fulano.php") or erroFuncao ();
	/*
		Usuário:
			Ocorreu um erro, desculpe-nos pelo transtorno, iremos resolvê-lo o mais rápido póssivel.
	*/
	
	/*
		Log:
			10/10/2010 as 10:10 10
				Arquivo: "Fulano.php"
				Linha: "1"
	*/
	
	// Mensagem Personalizada
	is_writable ("Beltrano.php") or erroFuncao ("Cara, o arquivo que você está procurando não existe !");
	/*
		Usuário:
			Cara, o arquivo que você está procurando não existe !
	*/
	
	/*
		Log:
			09/09/2009 as 09:09 09
				Arquivo: "Beltrano.php"
				Linha: "2"
	*/
	
	// Identificador
	is_writable ("Sicrano.php") or erroFuncao (true);
	/*
		Usuário:
			Erro Nº 543975346. Favor anotar o número e contactar o administrador
	*/
	
	/*
		Log:
			Erro Nº 543975346 de 08/08/2008 as 08:08 08
				Arquivo: "Sicrano.php"
				Linha: "3"
	*/
?>

Agora so falta uma última coisa, os erros do PHP. Seu site está pronto e debugado, por algum motivo que não sei qual apareceu um erro "E_WARNING" com a linha e o nome do arquivo, lembre-se que o usuário não pode saber tais informações por motivos de segurança, o que fazemos é não mostrar esse erro e sim redirecionalo para um log.

	function erroPHP ($numeroTipo, $mensagem, $arquivo, $linha) {		
		is_int ($numeroTipo) || $numeroTipo === "" or erroFuncao ();
		is_string ($mensagem) or erroFuncao ();
		is_string ($arquivo) or erroFuncao ();
		is_numeric ($linha) or erroFuncao ();
		
		$mensagemSistema = "Erro de " . date ("d/m/y") . " as " . date ("G:i s") . "\n";
		$mensagemSistema .= "\tMensagem: \"" . $mensagem . "\"\n";
		$mensagemSistema .= "\tArquivo: \"" . $arquivo . "\"\n";
		$mensagemSistema .= "\tLinha: \"" . $linha . "\"\n\n";
		
		@error_log ($mensagemSistema, 3, "c:/logPHP.txt")  or erroFuncao ();
	}
	
	set_error_handler ("erroPHP") or erroFuncao ();

Mas porque eu preciso dessa função se eu já debugei meu código e ele não contém erros ? Não sei cara, como eu falei em computação tudo é possível, o seguro morreu de velho :D

Explicação:
2ª até 5ª linha: Verifica se os parâmetros estão corretos
7ª até 10ª linha: Monta mensagem do log
11ª linha: Gera log
14ª linha: http://php.net/manual/en/function.set-error-handler.php, sempre quando ocorrer um erro do PHP ele redireciona para nossa função que gera o log

Acabou-se :) Agora que deu para entender o funcionamente segue o script completo:
<?php
	function erroFuncao ($tiposMensagens = false) {
		is_string ($tiposMensagens) || is_bool ($tiposMensagens) or exit ("Erro Nº 0. Favor anotar o número e contactar o administrador.");

		$mensagemSistema = date ("d/m/y") . " as " . date ("G:i s") . "\n";
		
		if ($tiposMensagens === true) {
			// Identificador deve ser único, esse método não é confiavél pois pode existir duas requisições  com o mesmo número
			$identificador = mt_rand (2, mt_getrandmax ());
			
			$mensagemSistema = "Erro Nº " . $identificador . " de " . date ("d/m/y") . " as " . date ("G:i s") . "\n";
			$mensagemUsuario = "Erro Nº " . $identificador . ". Favor anotar o número e contactar o administrador";
		}
		else if ($tiposMensagens === false)
			$mensagemUsuario = "Ocorreu um erro, desculpe-nos pelo transtorno, iremos resolvê-lo o mais rápido póssivel.";
		else
			$mensagemUsuario = $tiposMensagens;
		
		$debug = debug_backtrace () or exit ("Erro Nº 1. Favor anotar o número e contactar o administrador.");
		
		$mensagemSistema .= "\tArquivo: \"" . $debug[0]["file"] . "\"\n";
		$mensagemSistema .= "\tLinha: \"" . $debug[0]["line"] . "\"\n\n";
		
		error_log ($mensagemSistema, 3, "c:/logFuncao.txt") or exit ("Erro Nº 2. Favor anotar o número e contactar o administrador.");
		
		exit (json_encode ($mensagemUsuario));
	}
	
	function erroPHP ($numeroTipo, $mensagem, $arquivo, $linha) {		
		is_int ($numeroTipo) || $numeroTipo === "" or erroFuncao ();
		is_string ($mensagem) or erroFuncao ();
		is_string ($arquivo) or erroFuncao ();
		is_numeric ($linha) or erroFuncao ();
		
		$mensagemSistema = "Erro de " . date ("d/m/y") . " as " . date ("G:i s") . "\n";
		$mensagemSistema .= "\tMensagem: \"" . $mensagem . "\"\n";
		$mensagemSistema .= "\tArquivo: \"" . $arquivo . "\"\n";
		$mensagemSistema .= "\tLinha: \"" . $linha . "\"\n\n";
		
		@error_log ($mensagemSistema, 3, "c:/logPHP.txt")  or erroFuncao ();
	}
	
	set_error_handler ("erroPHP") or erroFuncao ();
?>

Vlw galera do bem, flowwwwwwwwwwwwwwwwwwwwwwwwwwwww

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.