runtime-handling-errors.md 6.78 KB
Newer Older
Funson Lee committed
1
错误处理
Funson Lee committed
2 3
===============

Funson Lee committed
4 5
Yii 内置了一个[[yii\web\ErrorHandler|error handler]]错误处理器,它使错误处理更方便,
Yii错误处理器做以下工作来提升错误处理效果:
Funson Lee committed
6

Funson Lee committed
7 8 9 10
* 所有非致命PHP错误(如,警告,提示)会转换成可获取异常;
* 异常和致命的PHP错误会被显示,在调试模式会显示详细的函数调用栈和源代码行数。
* 支持使用专用的 [控制器操作](structure-actions.md) 来显示错误;
* 支持不同的错误响应格式;
Funson Lee committed
11

Funson Lee committed
12 13
[[yii\web\ErrorHandler|error handler]] 错误处理器默认启用,
可通过在应用的[入口脚本](structure-entry-scripts.md)中定义常量`YII_ENABLE_ERROR_HANDLER`来禁用。
Funson Lee committed
14 15


Funson Lee committed
16
## 使用错误处理器 <a name="using-error-handler"></a>
Funson Lee committed
17

Funson Lee committed
18 19
[[yii\web\ErrorHandler|error handler]] 注册成一个名称为`errorHandler`[应用组件](structure-application-components.md)
可以在应用配置中配置它类似如下:
Funson Lee committed
20 21 22 23 24 25 26 27 28 29 30

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

Funson Lee committed
31
使用如上代码,异常页面最多显示20条源代码。
Funson Lee committed
32

Funson Lee committed
33
如前所述,错误处理器将所有非致命PHP错误转换成可获取异常,也就是说可以使用如下代码处理PHP错误:
Funson Lee committed
34 35 36 37 38 39 40 41 42 43 44 45 46 47

```php
use Yii;
use yii\base\ErrorException;

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

// execution continues...
```

Funson Lee committed
48 49
如果你想显示一个错误页面告诉用户请求是无效的或无法处理的,可简单地抛出一个 [[yii\web\HttpException|HTTP exception]]异常,
[[yii\web\NotFoundHttpException]]。错误处理器会正确地设置响应的HTTP状态码并使用合适的错误视图页面来显示错误信息。
Funson Lee committed
50 51 52 53 54 55 56 57

```php
use yii\web\NotFoundHttpException;

throw new NotFoundHttpException();
```


Funson Lee committed
58
## 自定义错误显示 <a name="customizing-error-display"></a>
Funson Lee committed
59

Funson Lee committed
60 61 62
[[yii\web\ErrorHandler|error handler]]错误处理器根据常量`YII_DEBUG`的值来调整错误显示,
`YII_DEBUG` 为 true (表示在调试模式),错误处理器会显示异常以及详细的函数调用栈和源代码行数来帮助调试,
`YII_DEBUG` 为 false,只有错误信息会被显示以防止应用的敏感信息泄漏。
Funson Lee committed
63

Funson Lee committed
64 65
> 补充: 如果异常是继承 [[yii\base\UserException]],不管`YII_DEBUG`为何值,函数调用栈信息都不会显示,
这是因为这种错误会被认为是用户产生的错误,开发人员不需要去修正。
Funson Lee committed
66

Funson Lee committed
67
[[yii\web\ErrorHandler|error handler]] 错误处理器默认使用两个[视图](structure-views.md)显示错误:
Funson Lee committed
68

Funson Lee committed
69 70 71
* `@yii/views/errorHandler/error.php`: 显示不包含函数调用栈信息的错误信息是使用,
`YII_DEBUG` 为 false时,所有错误都使用该视图。
* `@yii/views/errorHandler/exception.php`: 显示包含函数调用栈信息的错误信息时使用。
Funson Lee committed
72

Funson Lee committed
73 74
可以配置错误处理器的 [[yii\web\ErrorHandler::errorView|errorView]] 和 [[yii\web\ErrorHandler::exceptionView|exceptionView]] 属性
使用自定义的错误显示视图。
Funson Lee committed
75 76


Funson Lee committed
77
### 使用错误操作 <a name="using-error-actions"></a>
Funson Lee committed
78

Funson Lee committed
79 80
使用指定的错误[操作](structure-controllers.md) 来自定义错误显示更方便,
为此,首先配置`errorHandler`组件的 [[yii\web\ErrorHandler::errorAction|errorAction]] 属性,类似如下: 
Funson Lee committed
81 82 83 84 85 86 87 88 89 90 91

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

Funson Lee committed
92 93
[[yii\web\ErrorHandler::errorAction|errorAction]] 属性使用[路由](structure-controllers.md#routes)到一个操作,
上述配置表示不用显示函数调用栈信息的错误会通过执行`site/error`操作来显示。
Funson Lee committed
94

Funson Lee committed
95
可以创建`site/error` 操作如下所示:
Funson Lee committed
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115

```php
namespace app\controllers;

use Yii;
use yii\web\Controller;

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

Funson Lee committed
116
上述代码定义`error` 操作使用[[yii\web\ErrorAction]] 类,该类渲染名为`error`视图来显示错误。
Funson Lee committed
117

Funson Lee committed
118
除了使用[[yii\web\ErrorAction]], 可定义`error` 操作使用类似如下的操作方法:
Funson Lee committed
119 120 121 122 123 124 125 126 127 128 129

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

Funson Lee committed
130 131
现在应创建一个视图文件为`views/site/error.php`,在该视图文件中,如果错误操作定义为[[yii\web\ErrorAction]],
可以访问该操作中定义的如下变量:
Funson Lee committed
132

Funson Lee committed
133 134 135
* `name`: 错误名称
* `message`: 错误信息
* `exception`: 更多详细信息的异常对象,如HTTP 状态码,错误码,错误调用栈等。
Funson Lee committed
136

Funson Lee committed
137 138
> 补充: 如果你使用 [基础应用模板](start-installation.md) 或 [高级应用模板](tutorial-advanced-app.md),
错误操作和错误视图已经定义好了。
Funson Lee committed
139 140


Funson Lee committed
141
### 自定义错误格式 <a name="error-format"></a>
Funson Lee committed
142

Funson Lee committed
143 144 145 146
错误处理器根据[响应](runtime-responses.md)设置的格式来显示错误,
如果[[yii\web\Response::format|response format]] 响应格式为`html`, 会使用错误或异常视图来显示错误信息,如上一小节所述。
对于其他的响应格式,错误处理器会错误信息作为数组赋值给[[yii\web\Response::data]]属性,然后转换到对应的格式,
例如,如果响应格式为`json`,可以看到如下响应信息:
Funson Lee committed
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162

```
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
}
```

Funson Lee committed
163
可在应用配置中响应`response`组件的`beforeSend`事件来自定义错误响应格式。
Funson Lee committed
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185

```php
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;
                }
            },
        ],
    ],
];
```

Funson Lee committed
186
上述代码会重新格式化错误响应,类似如下:
Funson Lee committed
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204

```
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
    }
}
```