PHP 怎么PHP 错误追踪

wen PHP项目 1

本文目录导读:

PHP 怎么PHP 错误追踪

  1. 基础错误显示设置
  2. 自定义错误处理函数
  3. 异常处理(try-catch)
  4. 使用 debug_backtrace()
  5. 错误日志记录
  6. 使用 Xdebug 扩展
  7. 完整错误处理示例
  8. 常用调试函数
  9. 使用建议

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(); // 异常风格的堆栈

使用建议

  1. 开发环境:开启所有错误显示,便于调试
  2. 生产环境:关闭错误显示,记录到日志文件
  3. 关键业务:使用 try-catch 处理可预见的异常
  4. 第三方库:统一错误处理,避免被覆盖
  5. 日志分析:定期检查错误日志,使用工具如 Sentry、Logstash

选择哪种方式取决于你的具体需求和项目规模,对于小型项目,简单的 error_reporting 和 try-catch 就足够;大型项目推荐使用成熟的日志系统和错误监控服务。

抱歉,评论功能暂时关闭!