Introduction
In today's tutorial, I'll introduce Yii's error and exception handling and guide you through some introductory scenarios.
Wondering what Yii is? Check out our Introduction to the Yii Framework and Programming With Yii2 series.
What's the Difference Between Errors and Exceptions?
Errors are unexpected defects in our code often discovered first by users. They'll typically break program execution. It's important not only to break gracefully for the user but to inform the developer of the problem so it can be fixed.
Exceptions are created by the developer when a potentially predictable error condition occurs. In code where an exception might occur, the developer can throw() an exception to a robust error handler.
How Does Yii Manage These?
In Yii, non-fatal PHP errors (e.g. warnings and notices) are routed into catchable exceptions so you can decide how to react and respond to them. You can designate a controller action to process all of these exceptions. And you can customize the display format for errors, e.g. HTML, JSON, XML, etc.
Exceptions and fatal PHP errors can be assessed only in debug mode. In these kinds of development scenarios, Yii can display detailed call stack information and segments of source code (you can see this above in the title image).
Fatal errors are the kind of events that break application execution. These include out of memory, instantiating an object of a class that doesn't exist, or calling a function that doesn't exist.
For example:
$t = new Unknownobject();
Let's get started with some examples of error and exception handling.
Configuring Error and Exception Handling
First, we configure our application in frontend/config/main.php. The errorHandler is defined as a component, as shown below. This example is from my startup series application, Meeting Planner. Notice the errorHandler
configuration in components
:
<?php $params = array_merge( require(__DIR__ . '/params.php'), require(__DIR__ . '/params-local.php') ); return [ 'id' => 'mp-frontend', 'name' => 'Meeting Planner', 'basePath' => dirname(__DIR__), 'bootstrap' => ['log','\common\components\SiteHelper'], 'controllerNamespace' => 'frontend\controllers', 'catchAll'=> [], 'components' => [ 'assetManager' => [...], ... 'errorHandler' => [ 'errorAction' => 'site/error', 'maxSourceLines' => 20, ], ... ], ];
In the above example, errorAction
directs the user to my SiteController's error action.
More broadly, Yii offers a variety of configuration options for errorHandler
for redirection and data gathering:
Property | Type | Description |
---|---|---|
$callStackItemView | string | The path of the view file for rendering exceptions and errors call stack element. e.g. '@yii/views/errorHandler/callStackItem.php' |
$displayVars | array | List of the PHP predefined variables that should be displayed on the error page. e.g. ['_GET', '_POST', '_FILES', '_COOKIE', '_SESSION'] |
$errorAction | string | The route (e.g. site/error ) to the controller action that will be used to display external errors. |
$errorView | string | The path of the view file for rendering exceptions without call stack information. e.g. '@yii/views/errorHandler/error.php' |
$exceptionView | string | The path of the view file for rendering exceptions. e.g. '@yii/views/errorHandler/exception.php' |
$maxSourceLines | integer | Maximum number of source code lines to be displayed. |
$maxTraceSourceLines | integer | Maximum number of trace source code lines to be displayed. |
$previousExceptionView | string | The path of the view file for rendering previous exceptions. e.g. '@yii/views/errorHandler/previousException.php' |
Using errorActions to Direct Execution
Generally, when a user encounters a serious error, we want to redirect them to a friendly, descriptive error page.
That's what the errorAction
in errorHandler
does. It redirects to our SiteController's actionError:
return [ 'components' => [ 'errorHandler' => [ 'errorAction' => 'site/error', ], ] ];
In our SiteController, we define an explicit error
action:
namespace app\controllers; use Yii; use yii\web\Controller; class SiteController extends Controller { public function actions() { return [ 'error' => [ 'class' => 'yii\web\ErrorAction', ], ]; } }
Here's a basic error handler (you can read more about these here):
public function actionError() { $exception = Yii::$app->errorHandler->exception; if ($exception !== null) { return $this->render('error', ['exception' => $exception]); } }
You can also respond differently whether there is an error or whether the page request does not exist in your application:
public function actionError() { $exception = Yii::$app->errorHandler->exception; if ($exception instanceof \yii\web\NotFoundHttpException) { // all non existing controllers+actions will end up here return $this->render('pnf'); // page not found } else { return $this->render('error', ['exception' => $exception]); } }
Here's my current Page Not Found 404 error handler:
You could theoretically include a site map of links, suggested pages similar to the page request, a search feature and a contact support link on your error pages. All of these can help the user recover and move on gracefully.
Here's my current general error page (obviously I have features to add):
Catching Exceptions
If we want to monitor a section of code for problems, we can use a PHP try catch block. Below, we'll experiment by triggering a fatal divide by zero error:
use Yii; use yii\base\ErrorException; ... try { 10/0; } catch (ErrorException $e) { Yii::warning("Division by zero."); } ...
The catch
response above is to generate a warning for the log. Yii has extensive logging:
- Yii::trace(): log a message to trace how a piece of code runs. Primarily for development.
- Yii::info(): log a message that conveys information about the event.
- Yii::warning(): log a warning message that an unexpected event occurred
- Yii::error(): log a fatal error for investigation
If, instead of logging an event, you wish to direct the user to the error page we configured earlier, you can throw an exception with the event:
use yii\web\NotFoundHttpException; throw new NotFoundHttpException();
Here's an example where we throw an exception with a specific HTTP status code and customized message:
try { 10/0; } catch (ErrorException $e) { throw new \yii\web\HttpException(451, 'Tom McFarlin\'s humor is often lost on me (and lots of people).'); }
Here's what that code looks like to the user:
About Yii Logging
All errors in Yii are logged depending on how you've set them up. You may also be interested in my tutorial about Sentry and Rollbar for logging in Yii:
In Closing
I hope you enjoyed our exploration of error and exception handling. Watch for upcoming tutorials in our Programming With Yii2 series as we continue diving into different aspects of the framework.
If you'd like to see a deeper dive in Yii application development, check out our Building Your Startup With PHP series which uses Yii2's advanced template. It tells the story of programming each step of Meeting Planner. It's very useful if you want to learn about building applications in Yii from the ground up.
If you'd like to know when the next Yii2 tutorial arrives, follow me @lookahead_io on Twitter or check my instructor page.
Comments