接管错误处理·set_exception_handler()

<?php
declare(strict_types=1);
ini_set('display_errors', 'Off'); // 关闭打印错误信息
ini_set('error_reporting', E_ALL & ~E_DEPRECATED & ~E_STRICT); // 报告部分级别错误
ini_set('display_startup_errors', 'Off'); // 不显示启动过程中的错误
ini_set('log_errors', 'Off'); // 不记录脚本运行错误
ini_set('error_log', null); // 指定脚本运行错误日志文件

set_exception_handler(static function (Throwable $exception): void {
    $exceptionClass = $exception::class;
    $message = $exception->getMessage();
    $file = $exception->getFile();
    $line = $exception->getLine();
    $traceAsString = $exception->getTraceAsString();

    // 仿照标准错误处理程序的格式
    $data = "Fatal error: Uncaught $exceptionClass: $message in $file:$line" . PHP_EOL;
    $data .= 'Stack trace:' . PHP_EOL;
    $data .= $traceAsString . PHP_EOL;
    $data .= "  thrown in $file on line $line";

    // 加上错误发生时间
    $data = '[' . date('Y-m-d H:i:s') . "] $data" . PHP_EOL;

    // 错误日志文件
    $filename = __DIR__ . '/error.log';

    // 将错误信息写入错误日志文件
    file_put_contents($filename, $data, FILE_APPEND | LOCK_EX);

    // 向开发者发送告警邮件或短信,通知尽快修复错误
    // send_sms();

    // 向用户反馈友好错误提示信息
    // exit('系统异常,请稍后再试~~~');
});

$redis = new Redis();
$redis->connect('localhost');
$redis->auth('************'); // 重要提醒:这里需要使用错误密码以抛出异常

echo '----- END -----' . PHP_EOL; // 上面的Redis::auth()抛出了RedisException且未捕获,程序会中止,所以这里不会执行到


//========== 总结 ==========//
// 1、当程序抛出异常且未捕获,就会自动执行set_exception_handler()设置的回调函数,执行完回调函数后异常会中止,
//    注意这里说的中止是指不会再在页面输出错误信息(即便display_errors设置为On),抛出异常处的后续代码也不会再执行。
// 2、对于常驻内存程序(如使用Swoole等)使用set_exception_handler()是没有效果的。

Copyright © 2024 码农人生. All Rights Reserved