whoops 是 PHP 的一个错误处理框架,本文主要取自 whoops 官方文档,这个框架使用很简单,如果只是简单使用,那么参考快速使用即可,无须继续看下去,如果希望详细了解,可以继续看我的翻译。

快速使用

只需在脚本开头(项目的入口脚本,比如:index.php) 加入下示代码即可

$whoops = new Whoops\Run();
$whoops->pushHandler(new \Whoops\Handler\PlainTextHandler()); // 以纯文本方式输出错误信息
$whoops->register();

如果报错,则需要根据 whoops 配置php库的查找路径,或使用自动加载

基于我项目的目录结构可以参考配置

spl_autoload_register(function ($className) {
    require_once __DIR__ . '/../' . $className . '.php';
});/* 自动加载 */
$whoops = new Whoops\Run();
$whoops->pushHandler(new \Whoops\Handler\PlainTextHandler()); // 以纯文本方式输出错误信息
$whoops->register();
$a(); // 写了一个错误
/* 我的错误输出 */
/**
 Whoops\Exception\ErrorException: Undefined variable: a in file E:\library\php\demo\whoops-1.php on line 20
Stack trace:
  1. Whoops\Exception\ErrorException->() E:\library\php\demo\whoops-1.php:20
  2. Whoops\Run->handleError() E:\library\php\demo\whoops-1.php:20
 */

我的项目结构:

—————— 根目录
    |—— demo 文件夹
        |—— whoops-1.php (demo脚本) 
    |—— Whoops 文件夹

自此,可以正常使用了!

Whoops\Run

Run 类为执行的实例,并集成方法来控制whoops在该上下文中的执行,并控制处理程序堆栈

1.常量

string Run::EXCEPTION_HANDLER // 异常处理程序方法的名称
string Run::ERROR_HANDLER     // 错误处理程序方法的名称
string Run::SHUTDOWN_HANDLER  // 宕机处理程序方法的名称

2.方法

// 将新 handler 推入堆栈
Run::pushHandler(Whoops\HandlerInterface $handler)
 #=> Whoops\Run

// 弹出栈顶 handler
Run::popHandler()
 #=> Whoops\HandlerInterface

// 返回所有 handler
Run::getHandlers()
 #=> Whoops\HandlerInterface[]

// Returns a Whoops\Inspector instance for a given Exception
Run::getInspector(Exception $exception)
 #=> Whoops\Exception\Inspector

// 注册该 Whoops\Run 实例,当发生 错误、异常、宕机 时返回堆栈错误信息
Run::register()
 #=> Whoops\Run

// I'll let you guess this one
Run::unregister()
 #=> Whoops\Run

// 如果是:true,运行终止脚本执行 (默认: true)
Run::allowQuit($allowQuit = null)
 #=> bool

// 如果是:true,则允许Whoops将处理程序生成的输出直接发送到客户机
// 如果你希望使用程序处理,并把处理结果打包到 http响应中,则需要设置为 false(default: true)
Run::writeToOutput($send = null)
 #=> bool

// ** HANDLERS **
// These are semi-internal methods that receive input from
// PHP directly. If you know what you're doing, you can
// also call them directly

// 处理当前堆栈的异常。返回处理程序生成的输出
Run::handleException(Exception $exception)
 #=> string

// 处理当前堆栈的错误。错误被转换为SPL ErrorException实例
Run::handleError(int $level, string $message, string $file = null, int $line = null)
 #=> null

// 作为宕机处理程序钩子,捕获致命错误并通过当前堆栈处理它们:
Run::handleShutdown()
 #=> null

Whoops\Handler\Handler & Whoops\Handler\HandlerInterface

这个抽象类包含具体处理程序实现的基本方法,自定义处理类可以继承它,也可以实现 Whoops\Handler\HandlerInterface 接口

1.常量

int Handler::DONE          // 如果从HandlerInterface::handle返回,则什么也不做
int Handler::LAST_HANDLER  // 告诉whoops在此之后不再执行任何处理程序
int Handler::QUIT          // 告诉whoops立即退出脚本执行

2.方法

// 自定义处理程序应该公开此方法,一旦错误、异常等发生就会调用此方法。返回的常数,告诉接下来的处理逻辑
HandlerInterface::handle()
 #=> null | int

// 设置此处理程序的运行实例
HandlerInterface::setRun(Whoops\Run $run)
 #=> null

// 为该处理程序设置检查器实例
HandlerInterface::setInspector(Whoops\Exception\Inspector $inspector)
 #=> null

// 设置此处理程序要处理的异常
HandlerInterface::setException(Exception $exception)
 #=> null

Whoops\Exception\Inspector

Inspector类提供了检查异常实例的方法,尤其关注其帧/堆栈跟踪

1.方法

Inspector::__construct(Exception $exception)
 #=> null

// 返回正在检查的异常实例
Inspector::getException()
 #=> Exception

// 返回正在检查的异常的字符串名称,好的方式是执行:get_class($inspector->getException()
Inspector::getExceptionName()
 #=> string

// 返回正在检查的异常的字符串消息,好的方法是执行:$inspector->getException()->getMessage()
Inspector::getExceptionMessage()
 #=> string

// 返回堆栈中所有帧的迭代器实例,跟踪正在检查的异常
Inspector::getFrames()
 #=> Whoops\Exception\FrameIterator

Whoops\Exception\FrameCollection

FrameCollection类公开了一个接口来操作和检查框架实例的集合。FrameCollection对象是可序列化的

1.方法

// 返回集合中的帧数
FrameCollection::count()
 #=> int

// 使用可调用项筛选集合中的帧.
// 可调用的对象必须接受Frame对象并返回
// true保存在集合中,或false不保存在集合中
FrameCollection::filter(callable $callable)
 #=> FrameCollection

// See: array_map
// 可调用的对象必须接受Frame对象并返回
// 一个Frame对象,如果不匹配,跑出 UnexpectedValueException 异常
FrameCollection::map(callable $callable)
 #=> FrameCollection

Whoops\Exception\Frame

Frame类对异常堆栈跟踪中的单个帧建模。您可以使用它来检索诸如框架上下文、文件、行号之类的信息。此外,您还有向框架添加注释的可用功能,其他处理程序也可以使用这些功能。Frame 是可序列化的

1.方法

// 返回发生此帧的文件的文件路径。
// 可选的$short参数允许检索更短,人类可读的文件路径显示
Frame::getFile(bool $shortened = false)
 #=> string | null (Some frames do not have a file path)

// 返回此帧的行号
Frame::getLine()
 #=> int | null

// 如果发生,返回此帧的类名
Frame::getClass()
 #=> string | null

// 返回该帧的函数名(如果发生的话)
Frame::getFunction()
 #=> string | null

// 返回此帧的参数数组. 没有参数提供则返回空.
Frame::getArgs()
 #=> array

// 返回此帧所在文件的完整文件内容
Frame::getFileContents()
 #=> string | null

// 返回文件的行数组,可选范围为给定行号的范围. 
// 例如: Frame::getFileLines(0, 3)
// 一行一行的返回前三行
Frame::getFileLines(int $start = 0, int $length = null)
 #=> array | null

// 向此框架实例添加注释.注释是共享的
// context 操作可以改进注释的过滤
Frame::addComment(string $comment, string $context = 'global')
 #=> null

// 返回此实例的所有可选筛选的注释字符串上下文标识符。
Frame::getComments(string $filter = null)
 #=> array

Whoops\Handler\CallbackHandler

错误处理

CallbackHandler处理程序将常规PHP闭包包装为有效的处理程序。适用于快速原型或简单的处理程序。当您传递一个闭包来运行::pushHandler时,它会自动转换为CallbackHandler实例

<?php
use Whoops\Handler\Handler;
$run->pushHandler(function($exception, $inspector, $run) {
    var_dump($exception->getMessage());
    return Handler::DONE;
});

$run->popHandler() // #=> Whoops\Handler\CallbackHandler

1.方法

// 接受一个 callback
CallbackHandler::__construct($callable)
 #=> null

CallbackHandler::handle()
 #=> int | null

Whoops\Handler\JsonResponseHandler

JSON 格式的错误处理,返回格式如下:

{
  "error": {
    "type": "RuntimeException",
    "message": "Something broke!",
    "file": "/var/project/foo/bar.php",
    "line": 22,
     # if JsonResponseHandler::addTraceToOutput(true):
     "trace": [
        { "file": "/var/project/foo/index.php",
          "line": 157,
          "function": "handleStuffs",
          "class": "MyApplication\DoerOfThings",
          "args": [ true, 10, "yay method arguments" ] },
        # ... more frames here ...
     ]
  }
}

1.方法

// Should detailed stack trace output also be added to the
// JSON payload body?
JsonResponseHandler::addTraceToOutput(bool $yes = null)
 #=> bool

JsonResponseHandler::handle()
 #=> int | null

Whoops\Handler\PrettyPageHandler

一个很漂亮的错误处理页面,不过依赖 symfony 框架

1.方法

// Adds a key=>value table of arbitrary data, labeled by $label, to
// the output. Useful where you want to display contextual data along
// with the error, about your application or project.
PrettyPageHandler::addDataTable(string $label, array $data)
 #=> null

// Similar to PrettyPageHandler::addDataTable, but accepts a callable
// that will be called only when rendering an exception. This allows
// you to gather additional data that may not be available very early
// in the process.
PrettyPageHandler::addDataTableCallback(string $label, callable $callback)
 #=> null

// Returns all data tables registered with this handler. Optionally
// accepts a string label, and will only return the data under that
// label.
PrettyPageHandler::getDataTables(string $label = null)
 #=> array | array[]

// Sets the title for the error page
PrettyPageHandler::setPageTitle(string $title)
 #=> null

// Returns the title for the error page
PrettyPageHandler::getPageTitle()
 #=> string

// Returns a list of string paths where resources
// used by this handler are searched for - the template and CSS
// files.
PrettyPageHandler::getResourcesPaths()
 #=> array

// Adds a string path to the location of resources for the
// handler. Useful if you want to roll your own template
// file (pretty-template.php and pretty-page.css) while
// still using the logic this handler provides
PrettyPageHandler::addResourcePath(string $resourcesPath)
 #=> null

// Sets an editor to use to open referenced files, either by
// a string identifier, or as an arbitrary callable that returns
// a string or an array that can be used as an href attribute.
// Available built-in editors can be found here: https://github.com/filp/whoops/blob/master/docs/Open Files In An Editor.md

PrettyPageHandler::setEditor(string $editor)
PrettyPageHandler::setEditor(function ($file, $line) { return string })

// Additionally you may want that the link acts as an ajax request (e.g. Intellij platform)
PrettyPageHandler::setEditor(function ($file, $line) { 
        return array(
            'url' => "http://localhost:63342/api/file/?file=$file&line=$line",
            'ajax' => true
        ); 
    }
)
 #=> null

// Similar to PrettyPageHandler::setEditor, but allows you
// to name your custom editor, thus sharing it with the
// rest of the application. Useful if, for example, you integrate
// Whoops into your framework or library, and want to share
// support for extra editors with the end-user.
//
// $resolver may be a callable, like with ::setEditor, or a string
// with placeholders %file and %line.
// For example:
// $handler->addEditor('whatevs', 'whatevs://open?file=file://%file&line=%line')
PrettyPageHandler::addEditor(string $editor, $resolver)
 #=> null
 
PrettyPageHandler::handle()
 #=> int | null

Whoops\Util\Misc::isAjaxRequest()

// 只在AJAX触发的请求中使用特定的处理程序
if (Whoops\Util\Misc::isAjaxRequest()){
  $run->addHandler($myHandler);
}

Whoops\Util\Misc::isCommandLine()

// 只在php cli中使用特定的处理程序
if (Whoops\Util\Misc::isCommandLine()){
  $run->addHandler($myHandler);
}

参考whoops官方 API