<?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); // 指定脚本运行错误日志文件 register_shutdown_function(static function (): void { $error = error_get_last(); // 获取最后发生的错误,若无错误则返回null // 说明①:若有多个错误,只会获取到最后一个 // 说明②:可能是致命错误也可能是非致命错误(即不区分错误类型) // 只处理类型为E_ERROR的错误(即致命错误) if (is_array($error) && isset($error['type']) && $error['type'] === E_ERROR) { // 仿照标准错误处理程序的格式 $data = "Fatal error: {$error['message']} in {$error['file']} on line {$error['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); // 处理函数也可以使用exit()停止脚本执行 // exit('----- exit -----' . PHP_EOL); // 处理函数里的echo操作也是有效的,内容也会在页面上输出 echo '----- echo -----' . PHP_EOL; } }); test(); // 调用未定义函数会报500错误(Fatal error) //========== 总结 ==========// // 1、脚本正常执行完毕、执行exit、发生致命错误等出现程序中止的情况都会触发回调,所以需要通过error_get_last()判断是否发生错误。 // 2、若程序出现Fatal error,会先执行标准错误处理(即在页面输出错误信息),这是无法跳过的,然后才会调用开发者注册的回调函数。 // 3、register_shutdown_function()主要用于生产环境记录Fatal error,因为生产环境必须时刻屏蔽一切错误信息输出,如果生产环境出现 // Fatal error页面只会报500错误,开发者不知道发生错误的文件和行号就会很难排错,而register_shutdown_function()则可以帮开发者 // 把详细的错误信息记录下来。 // 4、处理函数并不是异步执行,在函数体里执行echo、exit也是有效的。 // 5、和set_error_handler()不同,register_shutdown_function()注册的回调函数会且只会执行一次。 // 6、对于常驻内存程序(如使用Swoole等)使用register_shutdown_function()是没有意义的,即便发生了致命错误也不会执行回调函数。
Copyright © 2025 码农人生. All Rights Reserved