1 关注者

处理错误

Yii 包含一个内置的 错误处理程序,它使错误处理比以前更愉快。特别是,Yii 错误处理程序执行以下操作来改进错误处理

  • 所有非致命 PHP 错误(例如警告、通知)都被转换为可捕获的异常。
  • 在调试模式下,异常和致命 PHP 错误会显示详细的调用堆栈信息和源代码行。
  • 支持使用专门的 控制器操作 来显示错误。
  • 支持不同的错误响应格式。

默认情况下,错误处理程序 已启用。你可以在应用程序的 入口脚本 中将常量 YII_ENABLE_ERROR_HANDLER 定义为 false 来禁用它。

使用错误处理程序

错误处理程序 注册为名为 errorHandler应用程序组件。你可以在应用程序配置中像下面这样配置它

return [
    'components' => [
        'errorHandler' => [
            'maxSourceLines' => 20,
        ],
    ],
];

使用上述配置,异常页面中显示的源代码行数最多为 20 行。

如前所述,错误处理程序将所有非致命 PHP 错误转换为可捕获的异常。这意味着你可以使用以下代码来处理 PHP 错误

use Yii;
use yii\base\ErrorException;

try {
    10/0;
} catch (ErrorException $e) {
    Yii::warning("Division by zero.");
}

// execution continues...

如果你想显示一个错误页面,告诉用户他的请求无效或意外,你可以简单地抛出一个 HTTP 异常,例如 yii\web\NotFoundHttpException。错误处理程序将正确设置响应的 HTTP 状态代码,并使用适当的错误视图来显示错误消息。

use yii\web\NotFoundHttpException;

throw new NotFoundHttpException();

自定义错误显示

错误处理程序 会根据常量 YII_DEBUG 的值调整错误显示。当 YII_DEBUGtrue(表示处于调试模式)时,错误处理程序将显示包含详细调用堆栈信息和源代码行的异常,以帮助更轻松地调试。当 YII_DEBUGfalse 时,只会显示错误消息,以防止泄露有关应用程序的敏感信息。

信息: 如果异常是 yii\base\UserException 的后代,则无论 YII_DEBUG 的值如何,都不会显示调用堆栈。这是因为此类异常被认为是由用户错误引起的,开发人员无需修复任何问题。

默认情况下, 错误处理程序 使用两个 视图 来显示错误

  • @yii/views/errorHandler/error.php:当需要显示错误而无需调用堆栈信息时使用。当 YII_DEBUGfalse 时,这是唯一显示的错误视图。
  • @yii/views/errorHandler/exception.php:当需要显示包含调用堆栈信息的错误时使用。

您可以配置错误处理程序的 errorViewexceptionView 属性,以使用您自己的视图来自定义错误显示。

使用错误操作

自定义错误显示的更好方法是使用专用的错误 操作。为此,首先配置 errorHandler 组件的 errorAction 属性,如下所示

return [
    'components' => [
        'errorHandler' => [
            'errorAction' => 'site/error',
        ],
    ]
];

errorAction 属性接受指向操作的 路由。上面的配置说明,当需要显示错误但没有调用堆栈信息时,应执行 site/error 操作。

您可以按如下方式创建 site/error 操作:

namespace app\controllers;

use Yii;
use yii\web\Controller;

class SiteController extends Controller
{
    public function actions()
    {
        return [
            'error' => [
                'class' => 'yii\web\ErrorAction',
            ],
        ];
    }
}

上面的代码使用 yii\web\ErrorAction 类定义 error 操作,该类使用名为 error 的视图渲染错误。

除了使用 yii\web\ErrorAction 外,您还可以使用操作方法定义 error 操作,如下所示:

public function actionError()
{
    $exception = Yii::$app->errorHandler->exception;
    if ($exception !== null) {
        return $this->render('error', ['exception' => $exception]);
    }
}

您现在应该创建一个位于 views/site/error.php 的视图文件。在此视图文件中,如果错误操作定义为 yii\web\ErrorAction,您可以访问以下变量

  • name:错误的名称;
  • message:错误消息;
  • exception:异常对象,您可以通过它检索更多有用的信息,例如 HTTP 状态代码、错误代码、错误调用堆栈等。

信息:如果您使用的是 基本项目模板高级项目模板,则已为您定义了错误操作和错误视图。

注意:如果您需要在错误处理程序中重定向,请按以下方式进行

Yii::$app->getResponse()->redirect($url)->send();
return;

自定义错误响应格式

错误处理程序根据 响应 的格式设置显示错误。如果 响应格式html,它将使用错误或异常视图显示错误,如上一节所述。对于其他响应格式,错误处理程序将异常的数组表示形式分配给 yii\web\Response::$data 属性,然后将其相应地转换为不同的格式。例如,如果响应格式为 json,您可能会看到以下响应

HTTP/1.1 404 Not Found
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8

{
    "name": "Not Found Exception",
    "message": "The requested resource was not found.",
    "code": 0,
    "status": 404
}

您可以通过在应用程序配置中响应 response 组件的 beforeSend 事件来自定义错误响应格式

return [
    // ...
    'components' => [
        'response' => [
            'class' => 'yii\web\Response',
            'on beforeSend' => function ($event) {
                $response = $event->sender;
                if ($response->data !== null) {
                    $response->data = [
                        'success' => $response->isSuccessful,
                        'data' => $response->data,
                    ];
                    $response->statusCode = 200;
                }
            },
        ],
    ],
];

上面的代码将重新格式化错误响应,如下所示

HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8

{
    "success": false,
    "data": {
        "name": "Not Found Exception",
        "message": "The requested resource was not found.",
        "code": 0,
        "status": 404
    }
}

发现错别字或您认为此页面需要改进?
在 github 上编辑它 !