Tratamento de erros e depuração
Após 32 aulas sobre programação, você sem dúvida já se deparou com várias dificuldades — páginas em branco, mensagens de erro incompreensíveis e a dificuldade de saber como usar o try/catch. Esta aula reúne todas as habilidades de depuração, levando você da fase de “encontrar bugs por sorte” para a de “resolução sistemática de problemas”.
1. Níveis de erro
O PHP possui três tipos de erros:
Notice ← "You may have overlooked something" (undefined variable, offset)
Warning ← "The code has a problem but can continue" (include file not found)
Fatal Error ← "The code has a serious error and must stop" (calling a non-existent function)
<?php
// Notice: undefined variable (PHP continues execution)
echo $undefinedVar; // Notice: Undefined variable $undefinedVar
// Warning: file not found (PHP continues execution)
include 'nonexistent.php'; // Warning: Failed opening...
// Fatal Error: calling a non-existent function (PHP stops)
thisFunctionDoesNotExist(); // Fatal Error: Call to undefined function
?>
2. Controle dos relatórios de erros
<?php
// Development: show all errors
error_reporting(E_ALL);
ini_set('display_errors', '1');
// Production: log but don't display
error_reporting(E_ALL);
ini_set('display_errors', '0');
ini_set('log_errors', '1');
ini_set('error_log', __DIR__ . '/php-errors.log');
?>
display_errors = On em um servidor de produção — as mensagens de erro podem expor caminhos de arquivos, senhas de bancos de dados e outras informações confidenciais. Os usuários devem ver uma página genérica de erro 500; os detalhes do erro são registrados no log.
▶ Exemplo: Configuração sensível ao ambiente
<?php
$isDev = ($_SERVER['SERVER_NAME'] ?? '') === 'localhost';
if ($isDev) {
error_reporting(E_ALL);
ini_set('display_errors', '1');
} else {
error_reporting(E_ALL);
ini_set('display_errors', '0');
ini_set('log_errors', '1');
ini_set('error_log', '/var/log/php/errors.log');
}
?>
3. Tratamento de exceções: try/catch/finally
<?php
function divide(float $a, float $b): float {
if ($b === 0.0) {
throw new Exception("Division by zero is not allowed!");
}
return $a / $b;
}
try {
echo divide(10, 2) . "<br>"; // 5
echo divide(10, 0) . "<br>"; // Throws an exception
} catch (Exception $e) {
echo "[Caught Exception] {$e->getMessage()}<br>";
echo "File: {$e->getFile()}<br>";
echo "Line: {$e->getLine()}<br>";
} finally {
echo "Whether success or failure, finally always runs (e.g., close files, release resources)<br>";
}
?>
| Bloco | Quando é executado |
|---|---|
try |
A execução começa aqui — as exceções são monitoradas |
catch |
É executado se uma exceção for lançada no bloco try |
finally |
Sempre é executado, independentemente das circunstâncias (geralmente usado para limpeza) |
4. Exceções personalizadas
<?php
class ValidationException extends Exception {
private array $errors;
public function __construct(array $errors, string $message = "Validation failed") {
parent::__construct($message);
$this->errors = $errors;
}
public function getErrors(): array {
return $this->errors;
}
}
class UserNotFoundException extends Exception {}
// Using custom exceptions
function findUser(int $id): array {
$users = [1 => ['name' => 'John'], 2 => ['name' => 'Jane']];
if (!isset($users[$id])) {
throw new UserNotFoundException("User ID {$id} does not exist");
}
return $users[$id];
}
function validateUsername(string $name): void {
$errors = [];
if ($name === '') $errors[] = 'Username cannot be empty';
if (strlen($name) > 50) $errors[] = 'Username is too long';
if (!empty($errors)) throw new ValidationException($errors);
}
// Unified exception handling
try {
validateUsername('');
$user = findUser(99);
} catch (ValidationException $e) {
echo "[Validation Failed]<br>" . implode("<br>", $e->getErrors());
} catch (UserNotFoundException $e) {
echo "[User Not Found] {$e->getMessage()}";
} catch (Exception $e) {
echo "[Unknown Error] {$e->getMessage()}";
}
?>
5. Registro em log
<?php
class AppLogger {
public function __construct(
private string $logDir
) {
if (!is_dir($logDir)) {
mkdir($logDir, 0755, true);
}
}
public function info(string $message, array $context = []): void {
$this->log('INFO', $message, $context);
}
public function error(string $message, array $context = []): void {
$this->log('ERROR', $message, $context);
}
private function log(string $level, string $message, array $context): void {
$date = date('Y-m-d');
$time = date('H:i:s');
$line = "[{$time}] [{$level}] {$message}";
if (!empty($context)) {
$line .= ' ' . json_encode($context, JSON_UNESCAPED_UNICODE);
}
$line .= "\n";
$file = "{$this->logDir}/app-{$date}.log";
file_put_contents($file, $line, FILE_APPEND | LOCK_EX);
}
}
$log = new AppLogger(__DIR__ . '/logs');
$log->info('User logged in', ['username' => 'John', 'ip' => $_SERVER['REMOTE_ADDR'] ?? '']);
$log->error('Payment failed', ['order_id' => 12345, 'reason' => 'Insufficient balance']);
?>
6. Técnicas de depuração
▶ Exemplo: Funções utilitárias de depuração
<?php
// Most commonly used debug output
$data = ['name' => 'John', 'skills' => ['PHP', 'MySQL']];
var_dump($data); // Detailed output (type + value)
// array(2) { ["name"]=> string(4) "John" ["skills"]=> ... }
print_r($data); // Concise output
// Array ( [name] => John [skills] => Array ( [0] => PHP [1] => MySQL ) )
// Formatted var_dump (recommended)
echo '<pre>'; print_r($data); echo '</pre>';
// Debug and terminate
var_dump($data); exit; // or die(var_dump($data));
?>
(1) Referência rápida para depuração
<?php
// Value + type
var_dump($variable);
// Only show in development
if ($isDev) {
echo '<pre>'; var_dump($data); echo '</pre>';
}
// Log it
error_log("Debug info: " . print_r($data, true));
// Check if execution reaches a certain line
echo "HERE"; exit; // or error_log("Reached this line");
// View the call stack
debug_print_backtrace();
// Check if a variable is set
var_dump(isset($var), empty($var));
?>
7. Buffer de saída e manipuladores de erro personalizados
<?php
// Output buffering: capture echo/print output
ob_start();
echo "This text won't be sent directly to the browser.";
$content = ob_get_clean(); // Get and clear the buffer
// $content is now "This text won't be sent directly to the browser."
// Custom error handler
function myErrorHandler(int $errno, string $errstr, string $errfile, int $errline): bool {
$message = "[{$errno}] {$errstr} in {$errfile}:{$errline}";
error_log($message);
if (ini_get('display_errors')) {
echo "<div style='background:#ffebee;padding:10px;margin:10px'>
<strong>PHP Error:</strong> {$message}
</div>";
}
return true; // Prevent PHP's default handling
}
set_error_handler('myErrorHandler');
// Test the custom error handler
echo $undefined; // Now displays in a nice HTML box
?>
❓ Perguntas Frequentes
P: Quando devo usar as verificações
try/catchem vez deif? R: Useifpara erros esperados (o usuário não preencheu seu e-mail). Usetry/catchpara erros inesperados (queda na conexão com o banco de dados, perda de permissão de arquivo).ifsignifica “Sei que isso pode dar errado”, enquantocatchsignifica “Não sei o que pode dar errado, mas se ocorrer uma falha, vou resolver o problema”.
P: Como faço para depurar uma página em branco? R: A causa mais comum é um erro fatal com
display_errors = Off. Passos para solucionar o problema: (1) adicioneerror_reporting(E_ALL); ini_set('display_errors', '1');; (2) verifique o log de erros do PHP; (3) insiraecho "1"; exit;em intervalos para descobrir em qual linha a execução é interrompida.
P: O que é o Xdebug? Eu preciso dele? R: O Xdebug é uma extensão profissional de depuração para PHP — permite definir pontos de interrupção, percorrer o código passo a passo e inspecionar variáveis. Para quem está começando, o
var_dumpjá é suficiente. Quando seu projeto ultrapassar 1.000 linhas, vale a pena instalá-lo. A combinação do VS Code com o Xdebug é tão prática quanto as Ferramentas de Desenvolvimento do navegador.
📖 Resumo
- Aviso < Alerta < Erro fatal — três níveis de erro
- Desenvolvimento:
display_errors On; Produção:display_errors Off+log_errors On try { } catch (ExceptionType $e) { } finally { }— o padrão de tratamento de exceções- Classes de exceção personalizadas (
class XxxException extends Exception) error_log()para registro de logs,var_dump() + exitpara depuração rápida- Solução de problemas relacionados à página em branco: primeiro ative
display_errorse, em seguida, verifique o registro de erros - O buffer de saída
ob_start()/ob_get_clean()controla a saída
📝 Exercícios
- Crie uma página de calculadora de divisão que utilize try/catch para lidar com a divisão por zero e exiba uma mensagem amigável.
- Crie uma classe base
AppExceptioncom as subclassesValidationExceptioneDatabaseException. Utilize-as na lógica de registro de usuários e identifique-as separadamente. - Adicione registros de log ao exercício 2: quando forem capturadas exceções, grave os detalhes do erro (carimbo de data/hora, arquivo, número da linha) em um arquivo de log.



