vinala/error

让处理和调试 PHP 错误变得不那么糟糕。

维护者

详细信息

github.com/vinala/error

源代码

v0.2.0 2016-11-14 15:58 UTC

This package is not auto-updated.

Last update: 2024-09-23 14:18:29 UTC


README

让处理和调试 PHP 错误变得不那么糟糕。

目录

特性

  • 调试和非调试模式
  • 将 PHP 错误(警告、通知等)转换为异常
    • 尊重全局 error_reporting 设置
  • 处理未捕获的异常和致命错误(包括解析错误)
  • CLI 错误屏幕(将错误写入 STDERR)
  • Web 错误屏幕(为网络浏览器渲染错误)
    • 非调试模式
      Web error screen in non-debug mode
      • 简单的错误消息
      • 不泄露任何内部信息
      • 不使用“oh no”等词汇的任何变体
    • 调试模式
      Web error screen in debug mode
      • 文件路径和行号
      • 突出显示的代码预览
      • 堆栈跟踪
      • 参数列表
      • 变量上下文
      • 输出缓冲区(也可以显示为 HTML)
      • 纯文本跟踪(用于复制粘贴)
  • 可以用来
    • 实现日志记录
    • 条件性地抑制或强制错误
    • 修改或添加错误屏幕的内容

要求

  • PHP 5.3 或更高版本

使用示例

use Vinala\Error\ErrorHandler;

$debug = true; // true during development, false in production
error_reporting(E_ALL | E_STRICT); // configure the error reporting

$errorHandler = new ErrorHandler($debug);
$errorHandler->register();

// trigger an error to see the error handler in action
echo $invalidVariable;

事件系统

  • 使用 kuria/event 库实现
  • 错误处理器在处理错误时触发事件
  • 两个内置错误屏幕实现都在渲染时触发事件

错误处理器事件

ErrorHandler 类可能触发的事件

error

  • 当发生 PHP 错误时触发
  • 参数
    1. 对象 $exception
      • ErrorExceptionVinala\Error\ContextualErrorException 的实例
    2. bool $debug
    3. bool &$suppressed
      • 错误抑制状态的引用
      • 错误可以被当前的 error_reporting 配置或其他事件处理器抑制

fatal

  • 当处理未捕获的异常或致命错误时触发
  • 参数
    1. 对象 $exception
    2. bool $debug
    3. FatalErrorHandlerInterface &$handler
      • 当前致命错误处理器的引用

emerg

  • 在处理致命错误期间抛出其他异常时触发
  • 此时还有更多未捕获的异常或致命错误将导致脚本终止
  • 参数
    1. 对象 $exception
    2. bool $debug

Web 错误屏幕事件

WebErrorScreen 类可能触发的事件

render

  • 非调试模式 下渲染时触发
  • 单个参数 - 包含以下键的事件数组
    • &title: 用于 <title>
    • &heading: 用于 <h1>
    • &text: 默认段落的文本内容
    • &extras: 主要部分之后的自定义 HTML
    • exception: 异常
    • output_buffer: string|null
    • screen: WebErrorScreen 的实例

render.debug

  • 调试模式 下渲染时触发
  • 单个参数 - 包含以下键的事件数组
    • &title: 用于 <title>
    • &extras: 主要部分之后的自定义 HTML
    • exception: 异常
    • output_buffer: string|null
    • screen: WebErrorScreen 的实例

layout.css

  • 在输出 CSS 样式时触发
  • 单个参数 - 包含以下键的事件数组
    • &css: CSS 输出
    • debug: 布尔值
    • screen: WebErrorScreen 的实例

layout.js

  • 在输出 JavaScript 代码时触发
  • 单个参数 - 包含以下键的事件数组
    • &js: JS 输出
    • debug: 布尔值
    • screen: WebErrorScreen 的实例

CLI 错误屏幕事件

CliErrorScreen 类可能触发的事件

render

  • 在非调试模式下渲染时触发
  • 单个参数 - 包含以下键的事件数组
    • &title:输出第一行
    • &output:错误消息
    • exception: 异常
    • output_buffer: string|null
    • screen: WebErrorScreen 的实例

render.debug

  • 在调试模式下渲染时触发
  • 单个参数 - 包含以下键的事件数组
    • &title:输出第一行
    • &output:错误消息
    • exception: 异常
    • output_buffer: string|null
    • screen: WebErrorScreen 的实例

事件监听器示例

注意

  • 如果您希望与 PHP 7 中的新异常层次结构兼容,请不要在监听器中对 Exception 类进行类型提示

记录日志

将未处理的错误记录到文件中。

use Vinala\Error\Util\Debug;

$errorHandler->on('fatal', function ($exception, $debug) {
    $logFilePath = sprintf('./errors_%s.log', $debug ? 'debug' : 'prod');

    $entry = sprintf(
        "[%s] %s - %s in file %s on line %d\n",
        date('Y-m-d H:i:s'),
        Debug::getExceptionName($exception),
        $exception->getMessage(),
        $exception->getFile(),
        $exception->getLine()
    );

    file_put_contents($logFilePath, $entry, FILE_APPEND | LOCK_EX);
});

禁用 "@" 操作符

此监听器会导致类似 echo @$invalidVariable; 的语句抛出异常,而不管“闭嘴”操作符。

$errorHandler->on('error', function ($exception, $debug, &$suppressed) {
    $suppressed = false;
});

修改错误屏幕

Web 错误屏幕的示例。

更改非调试错误屏幕的默认标签

use Vinala\Error\Screen\WebErrorScreen;

$errorHandler->on('fatal', function ($exception, $debug, $screen) {
   if (!$debug && $screen instanceof WebErrorScreen) {
        $screen->on('render', function ($event) {
            $event['heading'] = 'It is all your fault!';
            $event['text'] = 'You have broken everything and now I hate you.';
        });
    }
});

向调试屏幕添加自定义部分

use Vinala\Error\Screen\WebErrorScreen;

$errorHandler->on('fatal', function ($exception, $debug, $screen) {
   if ($debug && $screen instanceof WebErrorScreen) {
        $screen
            ->on('layout.css', function ($event) {
                $event['css'] .= '#custom-group {color: #f60000;}';
            })
            ->on('render.debug', function ($event) {
                $event['extras'] .= <<<HTML
<div id="custom-group" class="group">
    <div class="section">
        Example of a custom section
    </div>
</div>
HTML;
            })
        ;
    }
});