阿江 2017-10-05 06:51:06 6264次浏览 0条回复 1 0 0

说明

学习Yii Framework 2易2框架的过程是漫长的也是充满乐趣的以下是我学习Yii2框架时对官网英文资料(请参见原文网址)的翻译和代码实现提供了较完整的代码供你参考不妥之处请多多指正

原文网址:

http://www.yiiframework.com/doc-2.0/guide-runtime-handling-errors.html
http://www.yiiframework.com/doc-2.0/yii-web-errorhandler.html

本文主题:错误处理(Handling Errors)

Yii自带错误处理器(error handler),它为错误处理带来前所未有的快乐体验。 Yii错误处理器为错误处理进行了如下改进: 1)所有非最终(non-fatal)PHP错误,如warnings,notices级别的错误,这些错误被转换成可捕获的错误。 2)异常(Exception)和最终PHP错误将被显示出来,如果是调试模式(debug mode)还将显示更详尽的内存栈信息和相关行的源代码。 3)支持使用一个预定义的控制器动作来显示错误。 4)支持不同的错误响应格式。

错误处理器默认是启用的。你可以在入口脚本中设置常量YII_ENABLE_ERROR_HANDLER为false来禁用它。 D:\phpwork\advanced\frontend\web\index.php

defined('YII_ENABLE_ERROR_HANDLER') or define('YII_ENABLE_ERROR_HANDLER',false);

禁用后将由PHP来报错:

/*
Fatal error: Uncaught exception 'yii\base\InvalidParamException' with message 'The view file does not exist: D:\phpwork\advanced\frontend\views\layouts\empty22.php' in D:\phpwork\advanced\vendor\yiisoft\yii2\base\View.php on line 226
*/

D:\phpwork\advanced\frontend\controllers\SiteController.php

    public function actionIndex(){
		//错误代码:没有empty22模板
        $this->layout='empty22';
        return $this->render('widget');
    }
1、使用错误处理器(Using Error Handler)

错误处理器被注册为一个应用组件,它的名称是errorHandler,你可以在应用配置中进行设置:

return [
	'components'=>[
		'errorHandler'=>[
			//在异常页面中显示源代码行数不超过20行
			'maxSourceLines'=>20,
		],
	],
];

如前所述,错误处理器将所有的非最终PHP错误转为可捕捉的异常,也就是说你可以使用以下代码来处理PHP错误:

	use Yii;
	use yii\base\ErrorException;
	try{
		10/0;
	}catch(ErrorException $e){
		//将错误记录到日志中,可以通过日志系统查询到
		Yii::warning("Division by zero.");
		//使用下句代码可以更直观的看到异常情况
		//echo "Division by zero.";
	}
	//后续代码可以继续执行

当一个用户的请求无效或发生异常,你需要显示一个错误页面给他,可以抛出一个HTTP异常(HTTP exception),如yii\web\NotFoundHttpException,错误控制器将纠正响应的HTTP状态码,并使用合适的错误视图去显示错误信息。

D:\phpwork\advanced\frontend\controllers\SiteController.php

public function actionIndex(){
	throw new \yii\web\NotFoundHttpException('The requested page does not exist.');
}
测试结果:
/*
Not Found (#404)
The requested page does not exist.
The above error occurred while the Web server was processing your request.
Please contact us if you think this is a server error. Thank you.
2016-11-10 11:12:03
*/

显示以上错误信息,需要将main.php文件中的以下三行代码提前注释掉: D:\phpwork\advanced\frontend\config\main.php

        /*'errorHandler' => [
            'errorAction' => 'site/error',
        ],*/
2、自定义错误显示(Customizing Error Display)

错误处理器根据YII_DEBUG的值调整错误显示方式。当YII_DEBUG是true时,错误处理器在显示异常时会显示调用内存栈的详细信息和相应行的源代码,以便于调试;当YII_DEBUG为false时,仅错误消息被显示出来,而不显示异常和详情,以免泄露应用的敏感信息。 提示:如果异常继承自yii\base\UserException,无论YII_DEBUG值为多少,都只显示没有栈信息的错误,这是因为这类异常是由于用户错误操作造成,开发者不需要修复任何地方。 //NotFoundHttpException就是一个UserException throw new NotFoundHttpException('The requested page does not exist.');

默认情况下,错误处理器使用以下两个视图显示错误:

@yii/views/errorHandler/error.php:当错误需要显示时使用,此时不显示栈信息。当YII_DEBUG为false时,仅此视图被显示。
@yii/views/errorHandler/exception.php:当错误需要显示时使用,此时会显示栈信息。

你可以配置错误处理器的errorView和exceptionView属性来自定义错误显示视图。 D:\phpwork\advanced\frontend\config\main.php

        'errorHandler' => [
			//自定义错误显示模板
            'errorView'=>'@frontend/template/error.php',
			//自定义异常显示模板
            'exceptionView'=>'@frontend/template/exception.php',
        ],
使用错误动作(Using Error Actions)

自定义错误显示的一个更好方式是使用专用的action,要实现这种方式,先在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',
			],
		];
	}
}

上述代码定义error动作使用yii\web\ErrorAction类,这个类使用一个名为'error'的视图来渲染错误信息。 //'error'视图是指\frontend\views\site\error.php //'errorHandler'另外一种设置(仅供参考):

	    'errorHandler' => [
            'errorAction' => 'site/error',//使用视图:\frontend\views\site\error.php
            'errorView'=>'@frontend/template/error.php',//上句定义后,此句设置无效
            'exceptionView'=>'@frontend/template/exception.php',
        ],

你需要创建一个视图文件views/site/error.php,如果错误动作定义为yii\web\ErrorAction,在error.php视图文件中,你可以获取以下变量: name:错误的名称 message:错误信息 exception:异常对象,在其中包含了许多你可以处理的有用信息,如HTTP状态码,错误代码,错误栈信息等

除了使用yii\web\ErrorAction,你也可以使用一个动作方法来定义error动作

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

//实例:实现自定义的错误显示(生产环境) //需要将actions()中的'error'先注释掉:

            /*'error'=>[
                'class'=>'yii\web\ErrorAction',
            ],*/

//ErrorAction D:\phpwork\advanced\frontend\controllers\SiteController.php

//继承自CommonController,其中包括了error()方法
class SiteController extends CommonController{
    public function actionError(){
        $exception=Yii::$app->errorHandler->exception;
        if($exception!==null){
            if(isset($exception->statusCode)){
                $statusCode=$exception->statusCode;
            }else{
                $statusCode='';
            }
            $gourl=\Yii::$app->session->get('__returnUrl');
            if($gourl){
                $gourl=[['Go Back',$gourl]];
            }else{
                $gourl=[['Home','/']];
            }
            if($statusCode==404){
                //页面不存在,使用自定义的error()方法,并在3秒内自动跳转到网站首页
                return $this->error('Sorry!Your request page not exists!',$gourl,3);
            }elseif($statusCode==403){
                //无权限访问,使用自定义的error()方法,并在3秒内自动跳转到网站首页
                return $this->error('Sorry!You are not allowed to view this page!',$gourl,3);
            }else{
                //使用自定义的error()方法:
                return $this->error('Sorry!This page have some error!You can try again after one moment.',$gourl);
            }
        }else{
            return $this->error('Have Error!');
        }
    }

CommonController请参见: http://www.yiichina.com/topic/6736

提示:如果你使用的是基础项目模板或是高级项目模板,错误动作和错误视图已经定义好了。

注意:在错误处理器中,如果你需要重定向,可以使用如下代码:

Yii::$app->getResponse()->redirect($url)->send();
return;
自定义错误响应格式

错误处理器显示错误的格式是依照response的设置,如果response格式设置为html,它将使用error或exception的视图去显示错误。如果是其他响应格式,错误处理器会将异常数据赋为一个数组,放入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
    }
}

D:\phpwork\advanced\frontend\controllers\SiteController.php

    public function actionIndex(){
        Yii::$app->response->format=\yii\web\Response::FORMAT_JSON;
        throw new NotFoundHttpException('The requested page does not exist.');
    }
测试结果:
http://localhost:8082/
/*
{"name":"Not Found","message":"The requested page does not exist.","code":0,"status":404,"type":"yii\\web\\NotFoundHttpException"}
*/

(全文完)

    没有找到数据。
您需要登录后才可以回复。登录 | 立即注册