本文目录导读:

PHP 错误追踪是开发中非常重要的技能,能帮你快速定位问题,以下是几种常用的 PHP 错误追踪方法:
基础错误显示设置
开发环境配置
// 显示所有错误
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
// 生产环境建议关闭显示,记录到日志
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', '/path/to/error.log');
php.ini 配置
error_reporting = E_ALL display_errors = On log_errors = On error_log = /var/log/php_errors.log
自定义错误处理函数
// 自定义错误处理
function customErrorHandler($errno, $errstr, $errfile, $errline) {
$message = "Error [$errno]: $errstr in $errfile on line $errline";
// 记录到日志
error_log($message);
// 格式化输出
echo "<pre>";
echo "Error: " . $errstr . "\n";
echo "File: " . $errfile . "\n";
echo "Line: " . $errline . "\n";
echo "</pre>";
// 根据错误级别决定是否终止脚本
if ($errno == E_USER_ERROR) {
die("Fatal error occurred");
}
}
set_error_handler("customErrorHandler");
// 触发错误测试
trigger_error("Test warning", E_USER_WARNING);
异常处理(try-catch)
try {
// 可能抛出异常的代码
$result = 10 / 0;
} catch (DivisionByZeroError $e) {
echo "除零错误: " . $e->getMessage();
echo "文件: " . $e->getFile();
echo "行号: " . $e->getLine();
echo "堆栈跟踪: " . $e->getTraceAsString();
} catch (Exception $e) {
echo "其他异常: " . $e->getMessage();
}
使用 debug_backtrace()
function traceFunction() {
// 获取调用堆栈
$trace = debug_backtrace();
echo "<pre>";
foreach ($trace as $index => $call) {
echo "#{$index} ";
if (isset($call['file'])) {
echo $call['file'] . ":" . $call['line'];
}
echo " - " . $call['function'] . "(";
if (isset($call['args'])) {
echo implode(", ", $call['args']);
}
echo ")\n";
}
echo "</pre>";
}
function testFunction() {
traceFunction();
}
testFunction();
错误日志记录
// 手动记录错误
error_log("用户登录失败: " . $username, 3, "/var/log/app_errors.log");
// 记录到系统日志
error_log("数据库连接失败", 0);
// 记录到邮箱(生产环境慎用)
error_log("严重错误", 1, "admin@example.com");
使用 Xdebug 扩展
Xdebug 提供强大的调试功能:
// php.ini 配置 [xdebug] xdebug.mode = debug,develop xdebug.start_with_request = yes xdebug.log = /var/log/xdebug.log xdebug.idekey = "PHPSTORM" // 代码中启用 xdebug_break(); // 设置断点 var_dump($variable); // 增强的 var_dump
完整错误处理示例
<?php
// 完整错误处理类
class ErrorHandler {
private static $instance = null;
private $logFile;
private function __construct() {
$this->logFile = __DIR__ . '/error.log';
$this->registerHandlers();
}
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
private function registerHandlers() {
// 设置错误处理
set_error_handler([$this, 'handleError']);
// 设置异常处理
set_exception_handler([$this, 'handleException']);
// 注册关闭函数
register_shutdown_function([$this, 'handleShutdown']);
// 设置错误报告级别
error_reporting(E_ALL);
ini_set('display_errors', 0);
ini_set('log_errors', 1);
}
public function handleError($errno, $errstr, $errfile, $errline) {
$message = sprintf(
"[%s] Error %d: %s in %s:%d\n%s\n",
date('Y-m-d H:i:s'),
$errno,
$errstr,
$errfile,
$errline,
$this->getBacktrace()
);
$this->log($message);
// 根据错误类型决定是否终止
if (in_array($errno, [E_ERROR, E_USER_ERROR, E_PARSE, E_CORE_ERROR])) {
die("Fatal error occurred. Check error log.");
}
return true;
}
public function handleException($exception) {
$message = sprintf(
"[%s] Exception: %s in %s:%d\nStack trace:\n%s\n",
date('Y-m-d H:i:s'),
$exception->getMessage(),
$exception->getFile(),
$exception->getLine(),
$exception->getTraceAsString()
);
$this->log($message);
// 显示友好的错误页面
if (php_sapi_name() !== 'cli') {
http_response_code(500);
echo "Internal Server Error";
}
}
public function handleShutdown() {
$error = error_get_last();
if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
$this->handleError(
$error['type'],
$error['message'],
$error['file'],
$error['line']
);
}
}
private function getBacktrace() {
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
$output = "Backtrace:\n";
foreach ($trace as $index => $call) {
if ($index === 0) continue; // 跳过当前函数
$output .= sprintf(
" #%d %s%s%s (%s:%d)\n",
$index - 1,
isset($call['class']) ? $call['class'] . '->' : '',
$call['function'],
isset($call['file']) ? '' : ' [internal]',
$call['file'] ?? 'unknown',
$call['line'] ?? 0
);
}
return $output;
}
private function log($message) {
file_put_contents($this->logFile, $message, FILE_APPEND | LOCK_EX);
}
}
// 初始化错误处理
ErrorHandler::getInstance();
// 测试代码
try {
// 故意触发错误
echo $undefinedVariable;
throw new Exception("测试异常");
} catch (Exception $e) {
// 异常会被全局异常处理器捕获
}
常用调试函数
// 变量调试 var_dump($variable); // 显示变量类型和值 print_r($variable); // 打印可读的数组信息 debug_zval_refs($variable); // 显示引用信息 // 内存和性能调试 echo memory_get_usage(); // 当前内存使用 echo memory_get_peak_usage(); // 峰值内存使用 microtime(); // 时间测量 // 堆栈跟踪 debug_print_backtrace(); // 打印当前调用堆栈 echo (new Exception())->getTraceAsString(); // 异常风格的堆栈
使用建议
- 开发环境:开启所有错误显示,便于调试
- 生产环境:关闭错误显示,记录到日志文件
- 关键业务:使用 try-catch 处理可预见的异常
- 第三方库:统一错误处理,避免被覆盖
- 日志分析:定期检查错误日志,使用工具如 Sentry、Logstash
选择哪种方式取决于你的具体需求和项目规模,对于小型项目,简单的 error_reporting 和 try-catch 就足够;大型项目推荐使用成熟的日志系统和错误监控服务。