展示自定义错误
在Yii中,错误处理是非常灵活的,所以你可以为一种特定的错误创建你自己的错误处理方法。在这个小结中,我们将会以一个非常灵敏的方法处理一个404找不到的错误。我们将会展示一个404页面,它会基于输入栏中输入的内容提供建议的内容。
准备
- 按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的应用。
- 添加失败动作到你的
SiteController:
class SiteController extends Controller{// …public function actionFail(){throw new ServerErrorHttpException('Error message example.');}}
- 添加如下内容到
web/.htaccess:
RewriteEngine onRewriteCond %{REQUEST_FILENAME} !-fRewriteCond %{REQUEST_FILENAME} !-dRewriteRule . index.php
- 在
config/web.php文件中为urlManager组件配置友好的URL:
'components' => [// …'urlManager' => ['enablePrettyUrl' => true,'showScriptName' => false,],],
- 对于不存在的URL,展示
Not found异常:

- 同时,在我们的
actionFail中展示Internal Server Error异常:

- 现在我们希望为
Not Found页面创建一个自定义页面。
如何做…
现在我们需要修改Not Found页面的内容,但不考虑其它错误类型。为了达到这个目标,执行如下步骤:
- 打开
SiteController类并找到actions()方法:
class SiteController extends Controller{// ...public function actions(){return ['error' => ['class' => 'yii\web\ErrorAction',],'captcha' => ['class' => 'yii\captcha\CaptchaAction','fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,],];}// ...}
- 移除默认的
error部分,actions()如下所示:
<?phpclass SiteController extends Controller{// ...public function actions(){return ['captcha' => ['class' => 'yii\captcha\CaptchaAction','fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,],];}// ...}
- 添加自己的
actionError()方法:
class SiteController extends Controller{// ...public function actionError(){}}
- 打开原始的
\yii\web\ErrorAction类,复制它的动作内容到我们的actionError()中,并自定义它用于渲染自定义error-404视图,从而展示404错误码的Not Found错误:
<?php// ...use yii\base\Exception;use yii\base\UserException;class SiteController extends Controller{// ...public function actionError(){if (($exception =Yii::$app->getErrorHandler()->exception)== null) {$exception = new HttpException(404, Yii::t('yii','Page not found.'));}if ($exception instanceof HttpException) {$code = $exception->statusCode;} else {$code = $exception->getCode();}if ($exception instanceof Exception) {$name = $exception->getName();} else {$name = Yii::t('yii', 'Error');}if ($code) {$name .= " (#$code)";}if ($exception instanceof UserException) {$message = $exception->getMessage();} else {$message = Yii::t('yii', 'An internal server error occurred.');}if (Yii::$app->getRequest()->getIsAjax()) {return "$name: $message";} else {if ($code == 404) {return $this->render('error-404');} else {return $this->render('error', ['name' => $name,'message' => $message,'exception' => $exception,]);}}}}
- 使用一个自定义消息添加
views/site/error-404.php视图文件:
<?phpuse yii\helpers\Html;/* @var $this yii\web\View */$this->title = 'Not Found!'?><div class="site-error-404"><h1>Oops!</h1><p>Sorry, but requested page not found.</p><p>Please follow to <?= Html::a('index page', ['site/index'])?>to continue reading. Thank you.</p></div>
- 现在尝试访问不存在的URL,就能看到
error-404.php视图中的内容:

- 但是,对于一个失败的动作,我们能看到
error.php文件中默认的内容:

工作原理…
默认情况下,在yii2-app-basic应用中,我们在配置文件config/web.oho中为errorHandler组件配置errorAction为site/error。这意味着这个框架将会使用这个路由用于展示每一个被处理的异常:
'components' => ['errorHandler' => ['errorAction' => 'site/error',],],
在SiteController类中,我们使用内置的yii\web\ErrorAction类,它会渲染所谓的error.php视图:
class SiteController extends Controller{// ...public function actions(){return ['error' => ['class' => 'yii\web\ErrorAction',],'captcha' => ['class' => 'yii\captcha\CaptchaAction','fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,],];}// ...}
如果我们希望复写它的实现,我们可以 replace it in an inline actionError() method with our own custom content。
在这个小结中,我们添加了自己的if条件,用于渲染一个基于错误码的指定视图:
if ($code == 404) {return $this->render('error-404');} else {return $this->render('error', ['name' => $name,'message' => $message,'exception' => $exception,]);}
同时,我们可以为Not Found页面使用一个自定义设计。
参考
为了了解更多Yii中的错误处理,参考http://www.yiiframework.com/doc-2.0/guide-runtime-handling-errors.html。
