Qiang Xue
10 years ago
4 changed files with 180 additions and 56 deletions
@ -1,96 +1,217 @@ |
|||||||
Error Handling |
Handling Errors |
||||||
============== |
=============== |
||||||
|
|
||||||
> Note: This section is under development. |
Yii includes a built-in [[yii\web\ErrorHandler|error handler]] which makes error handling a much more pleasant |
||||||
|
experience than before. In particular, the Yii error handler does the followings to improve error handling: |
||||||
|
|
||||||
Error handling in Yii is different than handling errors in plain PHP. First of all, Yii will convert all non-fatal errors |
* All non-fatal PHP errors (e.g. warnings, notices) are converted into catchable exceptions. |
||||||
to *exceptions*: |
* Exceptions and fatal PHP errors are displayed with detailed call stack information and source code lines |
||||||
|
in debug mode. |
||||||
|
* Support using a dedicated [controller action](structure-actions.md) to display errors. |
||||||
|
* Support different error response formats. |
||||||
|
|
||||||
|
The [[yii\web\ErrorHandler|error handler]] is enabled by default. You may disable it by defining the constant |
||||||
|
`YII_ENABLE_ERROR_HANDLER` to be false in the [entry script](structure-entry-scripts.md) of your application. |
||||||
|
|
||||||
|
|
||||||
|
## Using Error Handler <a name="using-error-handler"></a> |
||||||
|
|
||||||
|
The [[yii\web\ErrorHandler|error handler]] is registered as an application component named `errorHandler`. |
||||||
|
You may configure it in the application configuration like the following: |
||||||
|
|
||||||
|
```php |
||||||
|
return [ |
||||||
|
'components' => [ |
||||||
|
'errorHandler' => [ |
||||||
|
'maxSourceLines' => 20, |
||||||
|
], |
||||||
|
], |
||||||
|
]; |
||||||
|
``` |
||||||
|
|
||||||
|
With the above configuration, the number of source code lines to be displayed in exception pages will be up to 20. |
||||||
|
|
||||||
|
As aforementioned, the error handler turns all non-fatal PHP errors into catchable exceptions. This means you can |
||||||
|
use the following code to deal with PHP errors: |
||||||
|
|
||||||
```php |
```php |
||||||
use yii\base\ErrorException; |
|
||||||
use Yii; |
use Yii; |
||||||
|
use yii\base\ErrorException; |
||||||
|
|
||||||
try { |
try { |
||||||
10/0; |
10/0; |
||||||
} catch (ErrorException $e) { |
} catch (ErrorException $e) { |
||||||
Yii::warning("Tried dividing by zero."); |
Yii::warning("Division by zero."); |
||||||
} |
} |
||||||
|
|
||||||
// execution may continue |
// execution continues... |
||||||
``` |
``` |
||||||
|
|
||||||
As demonstrated above you may handle errors using `try`-`catch`. |
If you want to show an error page telling the user that his request is invalid or unexpected, you may simply |
||||||
|
throw an [[yii\web\HttpException|HTTP exception]], such as [[yii\web\NotFoundHttpException]]. The error handler |
||||||
|
will correctly set the HTTP status code of the response and use an appropriate error view to display the error |
||||||
|
message. |
||||||
|
|
||||||
Second, even fatal errors in Yii are rendered in a nice way. This means that in debugging mode, you can trace the causes |
```php |
||||||
of fatal errors in order to more quickly identify the cause of the problem. |
use yii\web\NotFoundHttpException; |
||||||
|
|
||||||
|
throw new NotFoundHttpException(); |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
## Customizing Error Display <a name="customizing-error-display"></a> |
||||||
|
|
||||||
|
The [[yii\web\ErrorHandler|error handler]] adjusts error display according to the value of the constant `YII_DEBUG`. |
||||||
|
When `YII_DEBUG` is true (meaning in debug mode), the error handler will display exceptions with detailed call |
||||||
|
stack information and source code lines to help easier debugging. And when `YII_DEBUG` is false, only the error |
||||||
|
message will be displayed to prevent from revealing sensitive information of the application. |
||||||
|
|
||||||
|
> Info: If an exception is a descendant of [[yii\base\UserException]], no call stack will be displayed regardless |
||||||
|
the value of `YII_DEBUG`. This is because such exceptions are considered to be caused by user mistakes and the |
||||||
|
developers do not need to fix anything. |
||||||
|
|
||||||
|
By default, the [[yii\web\ErrorHandler|error handler]] displays errors using two [views](structure-views.md): |
||||||
|
|
||||||
|
* `@yii/views/errorHandler/error.php`: used when errors should be displayed WITHOUT call stack information. |
||||||
|
When `YII_DEBUG` is false, this is the only error view to be displayed. |
||||||
|
* `@yii/views/errorHandler/exception.php`: used when errors should be displayed WITH call stack information. |
||||||
|
|
||||||
Rendering errors in a dedicated controller action |
You can configure the [[yii\web\ErrorHandler::errorView|errorView]] and [[yii\web\ErrorHandler::exceptionView|exceptionView]] |
||||||
------------------------------------------------- |
properties of the error handler to use your own views to customize the error display. |
||||||
|
|
||||||
The default Yii error page is great when developing a site, and is acceptable for production sites if `YII_DEBUG` |
|
||||||
is turned off in your bootstrap `index.php` file. But you may want to customize the default error page to make it |
|
||||||
more suitable for your project. |
|
||||||
|
|
||||||
The easiest way to create a custom error page it is to use a dedicated controller action for error rendering. First, |
### Using Error Actions <a name="using-error-actions"></a> |
||||||
you'll need to configure the `errorHandler` component in the application's configuration: |
|
||||||
|
A better way of customizing the error display is to use dedicated error [actions](structure-controllers.md). |
||||||
|
To do so, first configure the [[yii\web\ErrorHandler::errorAction|errorAction]] property of the `errorHandler` |
||||||
|
component like the following: |
||||||
|
|
||||||
```php |
```php |
||||||
// ... |
return [ |
||||||
'components' => [ |
'components' => [ |
||||||
// ... |
'errorHandler' => [ |
||||||
'errorHandler' => [ |
'errorAction' => 'site/error', |
||||||
'errorAction' => 'site/error', |
], |
||||||
], |
] |
||||||
] |
]; |
||||||
|
``` |
||||||
|
|
||||||
|
The [[yii\web\ErrorHandler::errorAction|errorAction]] property takes a [route](structure-controllers.md#routes) |
||||||
|
to an action. The above configuration states that when an error needs to be displayed without call stack information, |
||||||
|
the `site/error` action should be executed. |
||||||
|
|
||||||
|
You can create the `site/error` action as follows, |
||||||
|
|
||||||
|
```php |
||||||
|
namespace app\controllers; |
||||||
|
|
||||||
|
use Yii; |
||||||
|
use yii\web\Controller; |
||||||
|
|
||||||
|
class SiteController extends Controller |
||||||
|
{ |
||||||
|
public function actions() |
||||||
|
{ |
||||||
|
return [ |
||||||
|
'error' => [ |
||||||
|
'class' => 'yii\web\ErrorAction', |
||||||
|
], |
||||||
|
]; |
||||||
|
} |
||||||
|
} |
||||||
``` |
``` |
||||||
|
|
||||||
With that configuration in place, whenever an error occurs, Yii will execute the `error`-action of the `site`-controller. |
The above code defines the `error` action using the [[yii\web\ErrorAction]] class which renders an error |
||||||
That action should look for an exception and, if present, render the proper view file, passing along the exception: |
using a view named `error`. |
||||||
|
|
||||||
|
Besides using [[yii\web\ErrorAction]], you may also define the `error` action using an action method like the following, |
||||||
|
|
||||||
```php |
```php |
||||||
public function actionError() |
public function actionError() |
||||||
{ |
{ |
||||||
$exception = \Yii::$app->errorHandler->exception; |
$exception = Yii::$app->errorHandler->exception; |
||||||
if ($exception !== null) { |
if ($exception !== null) { |
||||||
return $this->render('error', ['exception' => $exception]); |
return $this->render('error', ['exception' => $exception]); |
||||||
} |
} |
||||||
} |
} |
||||||
``` |
``` |
||||||
|
|
||||||
Next, you would create the `views/site/error.php` file, which would make use of the exception. The exception object has |
You should now create a view file located at `views/site/error.php`. In this view file, you can access |
||||||
the following properties: |
the following variables if the error action is defined as [[yii\web\ErrorAction]]: |
||||||
|
|
||||||
- `statusCode`: the HTTP status code (e.g. 403, 500). Available for [[yii\web\HttpException|HTTP exceptions]] only. |
* `name`: the name of the error; |
||||||
- `code`: the code of the exception. |
* `message`: the error message; |
||||||
- `message`: the error message. |
* `exception`: the exception object through which you can more useful information, such as HTTP status code, |
||||||
- `file`: the name of the PHP script file where the error occurs. |
error code, error call stack, etc. |
||||||
- `line`: the line number of the code where the error occurs. |
|
||||||
- `trace`: the call stack of the error. |
|
||||||
|
|
||||||
|
> Info: If you are using the [basic application template](start-installation.md) or the [advanced application template](tutorial-advanced-app.md), |
||||||
|
the error action and the error view are already defined for you. |
||||||
|
|
||||||
Rendering errors without a dedicated controller action |
|
||||||
------------------------------------------------------ |
|
||||||
|
|
||||||
Instead of creating a dedicated action within the Site controller, you could just indicate to Yii what class should |
### Customizing Error Response Format <a name="error-format"></a> |
||||||
be used to handle errors: |
|
||||||
|
The error handler displays errors according to the format setting of the [response](runtime-responses.md). |
||||||
|
If the the [[yii\web\Response::format|response format]] is `html`, it will use the error or exception view |
||||||
|
to display errors, as described in the last subsection. For other response formats, the error handler will |
||||||
|
assign the array representation of the exception to the [[yii\web\Response::data]] property which will then |
||||||
|
be converted to different formats accordingly. For example, if the response format is `json`, you may see |
||||||
|
the following response: |
||||||
|
|
||||||
|
``` |
||||||
|
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 |
||||||
|
|
||||||
```php |
|
||||||
public function actions() |
|
||||||
{ |
{ |
||||||
return [ |
"name": "Not Found Exception", |
||||||
'error' => [ |
"message": "The requested resource was not found.", |
||||||
'class' => 'yii\web\ErrorAction', |
"code": 0, |
||||||
], |
"status": 404 |
||||||
]; |
|
||||||
} |
} |
||||||
``` |
``` |
||||||
|
|
||||||
After associating the class with the error as in the above, define the `views/site/error.php` file, which will |
You may customize the error response format by responding to the `beforeSend` event of the `response` component |
||||||
automatically be used. The view will be passed three variables: |
in the application configuration: |
||||||
|
|
||||||
|
```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; |
||||||
|
} |
||||||
|
}, |
||||||
|
], |
||||||
|
], |
||||||
|
]; |
||||||
|
``` |
||||||
|
|
||||||
- `$name`: the error name |
The above code will reformat the error response like the following: |
||||||
- `$message`: the error message |
|
||||||
- `$exception`: the exception being handled |
|
||||||
|
|
||||||
The `$exception` object will have the same properties as outlined above. |
``` |
||||||
|
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 |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
Loading…
Reference in new issue