PHP 零基础教程

PHP 错误日志记录

将错误记录到文件中,可以确保你在排查生产环境中的问题时,不会将敏感的堆栈跟踪信息或服务器文件路径暴露给最终用户。虽然在开发阶段将错误直接显示在屏幕上非常有帮助,但 error_log() 函数为你提供了一种“静默”记录诊断信息的方法,方便日后随时审查。

1. error_log() 函数

error_log() 函数是将错误消息发送到服务器日志系统或指定文件的最核心机制。

它最常用的语法结构是 error_log(string $message, int $message_type = 0, string $destination = null, string $extra_headers = null)。当 $message_type 设置为 3 时,PHP 会将错误消息追加到由 $destination 指定的文件中。

<?php
// 定义日志文件的绝对路径
$logFile = __DIR__ . '/logs/app_errors.log';

// 模拟一次数据库连接失败
$dbConnected = false;

if (!$dbConnected) {
    // 生成带有时间戳的错误信息
    $timestamp = date('[Y-m-d H:i:s]');
    $errorMessage = "$timestamp 数据库连接失败,发生于文件:" . __FILE__ . PHP_EOL;
    
    // 将错误记录到我们自定义的文件中 (参数 3 表示追加到文件)
    error_log($errorMessage, 3, $logFile);
}
?>

在这个例子中,参数 3 告诉 PHP 直接将内容写入文件,而第三个参数提供了文件的系统路径。需要特别注意的是,你的 Web 服务器用户(例如 www-dataapache)必须对存放日志文件的目录拥有写入权限,否则日志将无法生成。

2. 通过 php.ini 配置 PHP 错误日志

与其在代码中为每一个潜在的问题手动调用 error_log(),不如直接配置 PHP 运行环境,让它自动将所有错误发送到一个专门的文件中。这可以通过修改 php.ini 文件中的 log_errorserror_log 指令来实现。

  • log_errors = On: 开启错误日志记录功能。
  • error_log = /path/to/your/custom_log_file.log: 指定错误信息应该写入的具体文件路径。

如果你没有权限修改服务器的 php.ini 文件,只要服务器配置允许,你可以在脚本内部尝试动态覆盖这些设置:

<?php
// 强制将当前脚本执行期间的错误记录到特定文件中
ini_set('log_errors', '1');
ini_set('error_log', __DIR__ . '/logs/runtime_errors.log');

// 这个由于访问未定义变量产生的 Notice,现在会被自动捕获并写入日志文件
echo $undefinedVariable; 
?>

3. 处理异常日志

在使用 try...catch 块时,一个非常专业的行业惯例是:先将异常的技术细节记录到日志中,然后再向用户显示一条友好的通用提示信息。这既保持了日志的清晰,又提供了可采取行动的数据,同时还兼顾了用户体验和安全性。

<?php
try {
    // 高风险操作:尝试打开一个不存在的文件
    if (!file_exists('data.txt')) {
        throw new Exception("关键数据文件丢失。");
    }
} catch (Exception $e) {
    // 将技术细节记录到日志中供开发者查看
    error_log("错误:" . $e->getMessage() . " 发生于第 " . $e->getLine() . " 行", 3, 'error.log');
    
    // 向普通用户显示通用的友好提示
    echo "我们正在经历一些技术困难。请稍后再试。";
}
?>

4. 错误日志的工作流

下面展示了应用程序在内部处理错误与向用户呈现信息时的不同工作流程。

  1. 执行应用程序逻辑 (Application Logic)
  2. 发生错误了吗? (Error Occurs?)
    1. 否 (No) -> 正常渲染页面。
    2. 是 (Yes) -> 进入异常捕获 (Catch Exception)。
  3. 捕获异常后:
    1. 后台操作: 将错误详情写入日志文件 (Write error to log file)。
    2. 前台操作: 向用户显示通用的错误提示 (Display generic error to user)。
  4. 继续执行 (Continue Execution) -> 渲染页面 (Render Page)