第六章 笔记(异常处理)

1.简单异常抛出

<?php
namespace app\api\model;
use think\Exception;

class Banner
{
    public static  function getBannerByID($id){
        //TODO 根据Banner  ID号 获取Banner信息
        try{
            1 / 0;
        }
        catch (Exception $ex)
        {
            //TODO;可以记录日志,正式项目将异常抛给客户端意义不大,最终还是需要服务器端做分析处理
            throw $ex;
        }
        return "This is banner test";
    }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<?php 
namespace app\api\controller\v1;
use think\Exception;
//use think\Validate;
//use app\api\validate\BaseValidate;
//use app\api\validate\TestValidate;
use app\api\validate\IdIsInt;
use app\api\model\Banner as BannerModel;
class Banner {
	/**
	 * 获取指定id的banner信息
	 * @url /banner/:id
	 * @http GET
	 * @id banner的id的号
	 * 
	 */
	public function getBanner($id)
	{
	    //正常情况下,3句话搞定
		(new IdIsInt())->goCheck();
        //直白的异常处理方式,但是代码不能复用,不能完美的服务大型项目
        try
        {
            $banner = BannerModel::getBannerByID($id);
        }catch (Exception $ex)
        {
            $err = [
                'error_code' => 10001,
                'msg' => $ex->getMessage()
            ];
            return json($err,400);
            //tp5需要使用json()转为json格式再返回
            //Postman 出现200状态,不是指成功的响应,而是成功的拿到了你想要的结果
        }
 }

在这里插入图片描述
2.异常分类

由用户行为导致
(通常没用通过验证器,没有查询到结果)
服务器自身异常
(代码错误,调用外部接口错误)
通常不需要记录日志通常记录日志
需要向用户返回具体信息不向用户返回具体信息

3.自定义异常处理

<?php
/**
 * Created by PhpStorm.
 * User: M_jh
 * Date: 2019/1/6
 * Time: 21:39
 */
namespace app\api\lib\exception;
use Exception;
use think\exception\Handle;

class ExceptionHandler extends Handle
{
    public function render(Exception $e)
    {
        return json('~~~~~~~~~~~~~~~~~~~~~~~~~~~');
//        return parent::render($e); // TODO: Change the autogenerated stub
    }
}

测试已通,需要注意的是自定义异常处理时候需要修改配置项exception_handle为自定义异常处理类路径。

<?php
/**
 * Created by PhpStorm.
 * User: M_jh
 * Date: 2019/1/6
 * Time: 21:29
 */

namespace app\api\lib\exception;


class BannerMissException extends BaseException
{
    public $code = 404;
    public $msg = 'banner未找见';
    public $errorCode = 40000;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<?php
/**
 * Created by PhpStorm.
 * User: M_jh
 * Date: 2019/1/6
 * Time: 21:39
 */
namespace app\api\lib\exception;
use Exception;
use think\exception\Handle;
use think\Request;

class ExceptionHandler extends Handle
{
    private $code;
    private $msg;
    private $errorCode;
    //需要返回客户端当前的请求URL路径
    public function render(Exception $e)
    {
//        return json('~~~~~~~~~~~~~~~~~~~~~~~~~~~');
//        return parent::render($e); // TODO: Change the autogenerated stub
        if ($e instanceof BaseException){
            //instanceof:判断其左边对象是否为其右边类的实例
            //判断是否自定义异常
            $this->code = $e->code;
            $this->msg = $e->msg;
            $this->errorCode = $e->errorCode;
        }
        else{
            $this->code = 500;
            $this->$msg = '服务器内部错误,不想你看到具体信息';
            $this->$errorCode = 999;
        }
        $request = Request::instance();
        $result = [
            'msg' => $this->msg,
            'errorCode' => $this->errorCode,
            'request_url' => $request->url()
        ];

        return json($result, $this->code);
    }
}

在这里插入图片描述

自定义异常处理和自定义验证器类似。
这里需要注意,仔细仔细再仔细!

4.日志
重定义日志目录

define('LOG_PATH', __DIR__ . '/../log/');
<?php
/**
 * Created by PhpStorm.
 * User: M_jh
 * Date: 2019/1/6
 * Time: 21:39
 */
namespace app\api\lib\exception;
use Exception;
use think\exception\Handle;
use think\Log;
use think\Request;

class ExceptionHandler extends Handle
{
    private $code;
    private $msg;
    private $errorCode;
    //需要返回客户端当前的请求URL路径
    public function render(Exception $e)
    {
//        return json('~~~~~~~~~~~~~~~~~~~~~~~~~~~');
//        return parent::render($e); // TODO: Change the autogenerated stub
        if ($e instanceof BaseException){
            //instanceof:判断其左边对象是否为其右边类的实例
            //判断是否自定义异常
            $this->code = $e->code;
            $this->msg = $e->msg;
            $this->errorCode = $e->errorCode;
        }
        else{
            $this->code = 500;
            $this->msg = '服务器内部错误,不想你看到具体信息';
            $this->errorCode = 999;
            $this->recordErrorLog($e);
        }
        $request = Request::instance();
        $result = [
            'msg' => $this->msg,
            'errorCode' => $this->errorCode,
            'request_url' => $request->url()
        ];

        return json($result, $this->code);
    }
    private function recordErrorLog(Exception $e){
    //需要重新开启日志
        Log::init([
           'type' => 'File',
            'path' => LOG_PATH,
            'level' => ['error']
        ]);
        Log::record($e->getMessage(), 'error');

    }
}

在这里插入图片描述在这里插入图片描述5.全局异常处理应用

    //当程序或者bug遇到不方便时候,我们需要做一些特殊的处理,可提高开发效率
    //自定义异常加判断无意义
    // Config::get(app_debug);读取配置文件变量,配置文件不建议做存储
    if (config('app_debug')){
        return parent::render($e);
    }else{
        $this->code = 500;
        $this->msg = '服务器内部错误,不想你看到具体信息';
        $this->errorCode = 999;
        $this->recordErrorLog($e);
    }
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<?php
/**
 * Created by PhpStorm.
 * User: M_jh
 * Date: 2019/1/8
 * Time: 19:31
 */

namespace app\api\lib\exception;


class ParamterException extends BannerMissException
{
    public $code = 400;
    public $msg = '参数错误';
    public $errorCode = 10000;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<?php 
namespace app\api\validate;
use app\api\lib\exception\ParamterException;
use think\Validate;
use think\Request;
use think\Exception;

class BaseValidate extends Validate
{
	public function goCheck(){
		$req = Request::instance()->param();
		$result = $this->Check($req);
		if (!$result) {
		    //抛出参数错误异常
		    $e = new ParamterException('');
		    throw $e;
//			$err = $this->error;
//			throw new Exception($err);//tp5默认异常
		}else{
			return true;
		}
	}
}

在这里插入图片描述
在这里插入图片描述 借助构造函数

    //构造函数
    public function __construct($params = [])
    {
        //先判断参数是否为数组
        if (!is_array($params)){
            return;//默认通过不处理
//            throw new Exception('参数必须为数组');
        }
        if (array_key_exists('code', $params)){
            $this->code = $params['code'];
        }
        if (array_key_exists('msg', $params)){
            $this->msg = $params['msg'];
        }
        if (array_key_exists('errorCode', $params)){
            $this->errorCode = $params['errorCode'];
        }
    }
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    	public function goCheck(){
        $params = Request::instance()->param();
		$result = $this->Check($params);
		if (!$result) {
		    //抛出参数错误异常
		    $e = new ParamterException([
                'msg' => $this->error,
                'errorCode' => 44444
            ]);
//		    $e->msg = $this->error;
//		    $e->errorCode = 44444;
		    throw $e;
//			$err = $this->error;
//			throw new Exception($err);//tp5默认异常
		}else{
			return true;
		}
	}

在这里插入图片描述
完善重构
批量验证

class IdIsInt extends BaseValidate
{
	protected $rule = [
			'name' => 'require|max:16',
			'email' => 'require|email',
			'id' => 'require|isInteger'
	];

	protected function isInteger($value,$rule = '',$data = '',$field = '')
	{
		if (is_numeric($value) && is_int($value + 0) && ($value + 0) > 0) {
		    return true;
		}
		else{
		    return $field.'必须是正整数';
		}

	}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(new IdIsInt())->batch()->goCheck();

在这里插入图片描述
总结:

  1. 构建参数校验层和全局异常处理层非常重要。
  2. 编程思路很重要。
  3. AOP 面向切面编程(本章笔记就是一个典型的应用,可以找找感觉),和面向对象不搭边。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值