目录:
第6章 AOP与全局异常处理
6-1 正确理解异常处理流程 13:23
6-2 固有的处理异常的思维模式与流程 14:23
6-3 理清思路,总结异常的分类_ 06:33
6-4 实现自定义全局异常处理 上 17:04
6-5 实现自定义全局异常处理 下 16:04
6-6 ThinkPHP5中的日志系统 14:34
6-7 在全局异常处理中加入日志记录 09:13
6-8 全局异常处理的应用 上 25:23
6-9 全局异常处理的应用 中 12:04
6-10 全局异常处理的应用 下 04:16
6-11 本章小结与AOP思想 12:56

6-5 实现自定义全局异常处理 下 16:04

6-5-1 测试思路:

6-5-1.1 调用model

v1/Banner.php里的getBanner里调用model层里的getBannerById(),
判断如果返回的为空,就抛出BannerMissException异常,抛出后,ExceptionHandler.php/render(Exception $e)就会接收到这个异常(所有抛出的异常,exceptionHandler都会捕捉到,由它判断异常的类型,而自定义异常都继承自BaseException异常,所以判断这个$e的异常是否属于BaseException自定义的异常,如果是就会出抛出自定义的异常处理.否则就抛出是服务器异常.
但要抛出这个自定义异常,首先BannerMissException要继承自Exception类,BaseException.php里继承自Exception类.BannerMissException又继承自BaseException.所以满足条件,没有问题

  1. 1 <?php
  2. 2 /**
  3. 3 * Created by PhpStorm.
  4. 4 * User: Haima
  5. 5 * Date: 2018/7/8
  6. 6 * Time: 15:58
  7. 7 */
  8. 8
  9. 9 namespace app\api\controller\v1;
  10. 10 use app\api\model\Banner as BannerModel;
  11. 11 use app\api\validate\IDMustBePostiveInt;
  12. 12 use app\lib\exception\BannerMissException;
  13. 13
  14. 14 class Banner
  15. 15 {
  16. 16 /**
  17. 17 * 获取指定id的banner信息
  18. 18 * @url /banner/:id
  19. 19 * @http GET
  20. 20 * @id banner的id号
  21. 21 */
  22. 22 public function getBanner($id)
  23. 23 {
  24. 24
  25. 25 (new IDMustBePostiveInt())->goCheck(); //验证$id是否为正整数
  26. 26 $banner = BannerModel::getBannerById($id);//调用model
  27. 27 if (!$banner){
  28. 28 throw new BannerMissException(); //判断结果不存在,抛出异常
  29. 29 }
  30. 30 // return $banner;
  31. 31 }
  32. 32 }

6-5-1.2 model层里验证数据返回null

return null;

  1. 1 <?php
  2. 2 /**
  3. 3 * Created by PhpStorm.
  4. 4 * User: Hiama
  5. 5 * Date: 2018/7/12
  6. 6 * Time: 1:16
  7. 7 */
  8. 8
  9. 9 namespace app\api\model;
  10. 10 class Banner
  11. 11 {
  12. 12 public static function getBannerById($id){
  13. 13 return null;
  14. 14 }
  15. 15 }

6-5-1.3 exceptionHandler.php判断异常类型,并抛出相应的异常

exceptionHandler.php里的render()方法判断Banner.php控制器抛出的是什么异常.
Banner.php控制器里抛出了BannerMissException异常,BannerMissException又继承自BaseException,
判断出$e最终属于BaseException异常,就会抛出自定义异常.
ExceptionHandler里获取当前被抛出的BannerMissException里定义的code,msg和errorCode三个属性,

所以ExceptionHandler最终就会抛出BannerMissException里定义的code,msg和errorCode三个属性信息

  1. 1 <?php
  2. 2 /**
  3. 3 * Created by PhpStorm.
  4. 4 * User: Haima
  5. 5 * Date: 2018/7/12
  6. 6 * Time: 3:11
  7. 7 */
  8. 8
  9. 9 namespace app\lib\exception;
  10. 10 use Exception;
  11. 11 use think\exception\Handle;
  12. 12 use think\Request;
  13. 13
  14. 14 class ExceptionHandler extends Handle
  15. 15 {
  16. 16 private $code;
  17. 17 private $msg;
  18. 18 private $errorCode;
  19. 19
  20. 20 public function render(Exception $e)
  21. 21 {
  22. 22 if($e instanceof BaseException){
  23. 23 $this->code = $e->code;
  24. 24 $this->msg = $e->msg;
  25. 25 $this->errorCode = $e->errorCode;
  26. 26 }
  27. 27 else{
  28. 28 $this->code = 500;
  29. 29 $this->msg = '服务器错误,不想给你看';
  30. 30 $this->errorCode = 999;
  31. 31 }
  32. 32 $request = Request::instance();
  33. 33 $result = array(
  34. 34 'msg' => $this->msg,
  35. 35 'error_code' => $this->errorCode,
  36. 36 'request_url' => $request->url()
  37. 37 );
  38. 38 return json($result,$this->code);
  39. 39 }
  40. 40 }
  1. <?php
  2. /**
  3. * Created by Haima.
  4. * Author:Haima
  5. * QQ:228654416
  6. * Date: 2018/7/12
  7. * Time: 20:48
  8. */
  9.  
  10. namespace app\lib\exception;
  11.  
  12. class BannerMissException extends BaseException
  13. {
  14. public $code = 404;
  15.  
  16. public $msg = '请求的Banner不存在';
  17.  
  18. public $errrCode = 40000;
  19. }
  1. 1 <?php
  2. 2 /**
  3. 3 * Created by Haima.
  4. 4 * Author:Haima
  5. 5 * QQ:228654416
  6. 6 * Date: 2018/7/12
  7. 7 * Time: 20:49
  8. 8 */
  9. 9
  10. 10 namespace app\lib\exception;
  11. 11
  12. 12
  13. 13 use think\Exception;
  14. 14
  15. 15 class BaseException extends Exception
  16. 16 {
  17. 17 //HTTP 状态码 404,200
  18. 18 public $code = 400;
  19. 19
  20. 20 //错误的具体信息
  21. 21 public $msg = '参数错误';
  22. 22
  23. 23 //自定义的错误码
  24. 24 public $errorCode = 10000;
  25. 25 }

6-5-1.4 处理的结果:

返回BannerMissException 里定义的三个属性值


6-6 ThinkPHP5中的日志系统 14:34

6-6.1 thinkphp5定义常量的位置

6-6.2 thinkphp5定义日志的位置

  在根目录的runtime/log/ 文件夹下面

  

  修改thinkphp生成日志的位置

  在public/index.php里添加

  define('LOG_PATH', __DIR__ . '/../log/'); //修改thinkphp生成日志的位置

  

6-7 在全局异常处理中加入日志记录 09:13

  具体可以参考手册里的说明:

  https://www.kancloud.cn/manual/thinkphp5/118127

  6-7.1 关闭日志写入的方法,在config.php里, 

  1. 1 'log' => [
  2. 2    // 可以关闭日志写入
  3. 3    'type' => 'test',
  4. 4   ],

  6-7.2 默认的话记录的日志级别是INFO,也可以指定日志级别:

    Log::record('测试日志信息,这是警告级别','notice');

日志级别

ThinkPHP对系统的日志按照级别来分类,并且这个日志级别完全可以自己定义,系统内部使用的级别包括:

  • log 常规日志,用于记录日志
  • error 错误,一般会导致程序的终止
  • notice 警告,程序可以运行但是还不够完美的错误
  • info 信息,程序输出信息
  • debug 调试,用于调试信息
  • sql SQL语句,用于SQL记录,只在数据库的调试模式开启时有效

系统提供了不同日志级别的快速记录方法,例如:  

  1. 1 Log::error('错误信息');
  2. 2 Log::info('日志信息');
  3. 3 // 和下面的用法等效
  4. 4 Log::record('错误信息','error');
  5. 5 Log::record('日志信息','info');

还封装了一个助手函数用于日志记录,例如:

  1. 1 trace('错误信息','error');
  2. 2 trace('日志信息','info');

自定义生成日志的例子:

config.php里关闭了系统自动生成日志

修改thinkphp生成日志的位置

在public/index.php里

  define('LOG_PATH', __DIR__ . '/../log/'); //修改thinkphp生成日志的位置

  

在Banner.php控制器里临时抛出服务器异常做测试

ExceptionHandler里封装服务器异常recordErrorLog() 生成日志的函数

ExceptionHandler里判断抛出的异常是服务器异常,走else里的代码,并调用封装的recordErrorLog() 生成日志的函数,写日志

因为config.php里关闭了系统自动写日志,所以在recordErrorLog() 函数里要初始化一下日志

Log::record() 记录日志信息到内存 上面需要引入 use think\Log;

  1. Log::record('测试日志信息,这是警告级别','notice');

  1. 1 <?php
  2. 2 /**
  3. 3 * Created by PhpStorm.
  4. 4 * User: Haima
  5. 5 * Date: 2018/7/12
  6. 6 * Time: 3:11
  7. 7 */
  8. 8
  9. 9 namespace app\lib\exception;
  10. 10 use Exception;
  11. 11 use think\exception\Handle;
  12. 12 use think\Log;
  13. 13 use think\Request;
  14. 14
  15. 15 class ExceptionHandler extends Handle
  16. 16 {
  17. 17 private $code;
  18. 18 private $msg;
  19. 19 private $errorCode;
  20. 20
  21. 21 public function render(Exception $e)
  22. 22 {
  23. 23 if($e instanceof BaseException){
  24. 24 $this->code = $e->code;
  25. 25 $this->msg = $e->msg;
  26. 26 $this->errorCode = $e->errorCode;
  27. 27 }
  28. 28 else{
  29. 29 $this->code = 500;
  30. 30 $this->msg = '服务器错误,不想给你看';
  31. 31 $this->errorCode = 999;
  32. 32 $this->recordErrorLog($e); //调用服务器异常错误
  33. 33 }
  34. 34 $request = Request::instance();
  35. 35 $result = array(
  36. 36 'msg' => $this->msg,
  37. 37 'error_code' => $this->errorCode,
  38. 38 'request_url' => $request->url()
  39. 39 );
  40. 40 return json($result,$this->code);
  41. 41 }
  42. 42
  43. 43   //服务器异常错误
  44. 44   private function recordErrorLog(Exception $e){
  45. 45 Log::init([
  46. 46 'type'=>'File', //生成的类型是文件
  47. 47 'path'=>LOG_PATH, //日志生成的路径 ,这里LOG_PATH的路径已经在public/index.php里定义了
  48. 48 'level'=>['error'] // 日志记录级别,使用数组表示
  49. 49 ]);
  50. 50 Log::record($e->getMessage(),'error'); //写入日志
  51. 51 }
  52. 52 }

给控制器发送请求:

此时已经在项目根目录里自动成功日志目录了


6-8 全局异常处理的应用 上 25:23

读取application\config.php配置文件里内容的方法

方法一:

  config('app_debug')

方法二:

  Config::get('app_debug');

 注意:

配置文件里的内容只能读取它里的某些配置信息,不要用它来做数据保存,

如果要保存数据可以写入数据库,redis缓存,thinkphp自提缓存,或者其它缓存的地方,或者保存到全局变量里

做全局异常处理,前/后台开发人员分别显示不同报错的方式

前端人员显示报错的页面,后端人员显示报错的json信息

思路:

在ExceptionHandler.php里的服务器异常里做判断,

判断配置里debug是否为true

(把它做为一个开关,通常上线后会关闭debug调适,这样服务器异常就会开启,异常就会写入日志里,当然你也可以自定义一个开关),

如果debug为ture就显示tp5框架自身的报错页面,给前台开发人员看,

否则就显示json的报错信息并写入日志中,给后端的开发人员看.

控制器里临时抛出服务器异常

ExceptionHandler.php里读取debug值做为写日志信息的开关判断

  1. 1 <?php
  2. 2 /**
  3. 3 * Created by PhpStorm.
  4. 4 * User: Haima
  5. 5 * Date: 2018/7/12
  6. 6 * Time: 3:11
  7. 7 */
  8. 8
  9. 9 namespace app\lib\exception;
  10. 10 use Exception;
  11. 11 use think\exception\Handle;
  12. 12 use think\Log;
  13. 13 use think\Request;
  14. 14
  15. 15 class ExceptionHandler extends Handle
  16. 16 {
  17. 17 private $code;
  18. 18 private $msg;
  19. 19 private $errorCode;
  20. 20
  21. 21 public function render(Exception $e)
  22. 22 {
  23. 23 if($e instanceof BaseException){
  24. 24 //如果是自定义异常,则控制http状态码,不需要记录日志
  25. 25 //因为这些通常是因为客户端传递参数错误或者是用户请求造成的异常
  26. 26 //不应当记录日志
  27. 27 $this->code = $e->code;
  28. 28 $this->msg = $e->msg;
  29. 29 $this->errorCode = $e->errorCode;
  30. 30 }
  31. 31 else{
  32. 32 // 如果是服务器未处理的异常,将http状态码设置为500,并记录日志
  33. 33 //Config::get('app_debug'); //获取config.php里的配置信息
  34. 34 if (config('app_debug')){ //获取config.php里的配置信息如果是true走这里
  35. 35 // 如果是前台调适人员看就显示json格式错误
  36. 36 // 调试状态下需要显示TP默认的异常页面,因为TP的默认就是页面
  37. 37 // 很容易看出问题
  38. 38 return parent::render($e); //调用thinkphp5默认的报错页面
  39. 39 }
  40. 40 //如果是后台调适人员看就显示json格式错误
  41. 41 $this->code = 500;
  42. 42 $this->msg = '服务器错误,不想给你看';
  43. 43 $this->errorCode = 999;
  44. 44 $this->recordErrorLog($e); //调用服务器异常错误
  45. 45 }
  46. 46 $request = Request::instance();
  47. 47 $result = array(
  48. 48 'msg' => $this->msg,
  49. 49 'error_code' => $this->errorCode,
  50. 50 'request_url' => $request->url()
  51. 51 );
  52. 52 return json($result,$this->code);
  53. 53 }
  54. 54
  55. 55 //服务器异常错误
  56. 56 private function recordErrorLog(Exception $e){
  57. 57 Log::init([
  58. 58 'type'=>'File', //生成的类型是文件
  59. 59 'path'=>LOG_PATH, //日志生成的路径
  60. 60 'level'=>['error'] // 日志记录级别,使用数组表示
  61. 61 ]);
  62. 62 Log::record($e->getMessage(),'error'); //写入日志
  63. 63 }
  64. 64 }

为false时:写入json日志

'app_debug' => false,

访问:

已经写入日志中:

 为true时:显示报错页面,并不会写入自定义的log目录的日志中

'app_debug' => true,

访问:

自定义的异常不显示页面报错

自定义的异常就显示我们自定义的json形式的报错就可以了,没有必要再显示页面的报错了(没有意义),所以就不用再做if判断了,

应用实例:

思路:

所有的整个参数验证层的错误处理都集中在BaseValidate这里,它承担了所有验证层的验证工作.是唯的验证入口

当客户访问z.com/banner/0.1时,banner.php/getBanner调用BaseValidate里的goCheck()方法验证,

goCheck()方法通过$this->check($params)调用IDMustBePostiveInt验证传入的$id是不是正整数

(IDMustBePostiveInt已经继承BaseValidate,BaseValidate 又继承 Validate,所以可以用$this->check($params)直接调用到),

当传入的参数不正确,BaseValidate验证不通过,抛出异常(这里需要它返回一个json结构体的消息,还要指明错误的原因,而不应该被反回服务器错误信息给隐藏掉),

ExceptionHandler捕捉到异常,并判断是异常类型后,抛出相应的异常信息.

优势:BaseValidate只管抛出异常,异常的类型交由ExceptionHandler来判断,然后决定抛出什么样的异常.

banner.php 里:

  1. 1 <?php
  2. 2 /**
  3. 3 * Created by PhpStorm.
  4. 4 * User: Haima
  5. 5 * Date: 2018/7/8
  6. 6 * Time: 15:58
  7. 7 */
  8. 8
  9. 9 namespace app\api\controller\v1;
  10. 10 use app\api\model\Banner as BannerModel;
  11. 11 use app\api\validate\IDMustBePostiveInt;
  12. 12 use app\lib\exception\BannerMissException;
  13. 13 use think\Exception;
  14. 14
  15. 15 class Banner
  16. 16 {
  17. 17 /**
  18. 18 * 获取指定id的banner信息
  19. 19 * @url /banner/:id
  20. 20 * @http GET
  21. 21 * @id banner的id号
  22. 22 */
  23. 23 public function getBanner($id)
  24. 24 {
  25. 25
  26. 26 (new IDMustBePostiveInt())->goCheck(); //验证$id是否为正整数
  27. 27 $banner = BannerModel::getBannerById($id);//调用model
  28. 28 if (!$banner){
  29. 29 // throw new BannerMissException(); //判断结果不存在,抛出异常
  30. 30 throw new Exception('服务器内部异常'); //临时抛出服务器异常测试用
  31. 31 }
  32. 32 // return $banner;
  33. 33 }
  34. 34 }

BaseValidate里:

  1. 1 <?php
  2. 2 /**
  3. 3 * Created by PhpStorm.
  4. 4 * User: Administrator
  5. 5 * Date: 2018/7/10
  6. 6 * Time: 21:49
  7. 7 */
  8. 8
  9. 9 namespace app\api\validate;
  10. 10
  11. 11 use app\lib\exception\parameterException;
  12. 12 use think\Exception;
  13. 13 use think\Request;
  14. 14 use think\Validate;
  15. 15
  16. 16 class BaseValidate extends Validate
  17. 17 {
  18. 18
  19. 19 //所有的整个参数验证层的错误处理都集中在这里,承担了所有验证层的验证工作
  20. 20 public function goCheck()
  21. 21 {
  22. 22 //获取http传入的参数
  23. 23 //方法一:
  24. 24 // $request = Request::instance();
  25. 25 // $params = $request->param();
  26. 26 // 方法二:
  27. 27 $params = Request::instance()->param();
  28. 28 //对参数进行校验
  29. 29 if(!$this->check($params)){
  30. 30
  31. 31 // 这里需要它返回一个json结构体的消息,还要指明错误的原因,
  32. 32 // 而不应该被反回服务器错误信息给隐藏掉
  33. 33 $e = new parameterException();
  34. 34 //用验证器里定义的错误信息重写parameterException下的$msg属性,
  35. 35 //这样就能正常报出验证器里定义的异常信息了
  36. 36 $e->msg=$this->error;
  37. 37 // 抛出的必需是一个Exception异常,
  38. 38 // 因为parameterException必需继承自BaseException,而BaseException已经继承了Exception.
  39. 39 // 所以parameterException自然也就继承了Exception
  40. 40 throw $e; //优势,只管抛出异常,异常的类型交由ExceptionHandler来判断,然后决定抛出什么样的异常
  41. 41
  42. 42 /* $error = $this->error;
  43. 43 throw new Exception($error);*/
  44. 44 }
  45. 45 else{
  46. 46 return true;
  47. 47 }
  48. 48 }
  49. 49 }

IDMustBePostiveInt验证器里

验证必需为正整数

  1. 1 <?php
  2. 2 /**
  3. 3 * Created by PhpStorm.
  4. 4 * User: Administrator
  5. 5 * Date: 2018/7/10
  6. 6 * Time: 12:18
  7. 7 */
  8. 8
  9. 9 namespace app\api\validate;
  10. 10
  11. 11 class IDMustBePostiveInt extends BaseValidate
  12. 12 {
  13. 13 protected $rule = [
  14. 14 'id' => 'require|isPositiveInteger'
  15. 15 ];
  16. 16
  17. 17 protected function isPositiveInteger($value,$rule='', $data='', $field='')
  18. 18 {
  19. 19 if(is_numeric($value) && is_int($value + 0) && ($value + 0) >0)
  20. 20 {
  21. 21 return true;
  22. 22 }
  23. 23 else
  24. 24 {
  25. 25 return $field.'必需是正整';
  26. 26 }
  27. 27 }
  28. 28 }

新建一个parameterException.php异常处理器,并继承BaseException

(当参数验证不通过时,它将被BaseValidate抛出异常)

  1. 1 <?php
  2. 2 /**
  3. 3 * Created by Haima.
  4. 4 * Author:Haima
  5. 5 * QQ:228654416
  6. 6 * Date: 2018/7/15
  7. 7 * Time: 10:48
  8. 8 */
  9. 9
  10. 10 namespace app\lib\exception;
  11. 11
  12. 12
  13. 13 class parameterException extends BaseException
  14. 14 {
  15. 15 public $code = 400;
  16. 16 //随便定义一个通用的提示信息,之后validate抛出异常信息时,会被重写成validate里定义的错误信息
  17. 17 public $msg = '参数错误';
  18. 18 //通过参数错误,凡是被验证层检查出来的错误都返回一个10000
  19. 19 public $errorCode = 10000;
  20. 20 }

ExceptionHandler里判断异常类型,并抛出相应的异常信息

ExceptionHandler里捕捉到$e异常后,判断是属于BaseExcetion参数错误异常,

捕捉到的BaseValidate里抛出的parameterException里的异常

所有就把parameterException的异常信息给继承过来,BaseValidate又改写了$msg属性,BaseValidate里的$this->error取的又是IDMustBePostiveInt里定义的错误信息

最终于会抛出验证器IDMustBePostiveInt里定义的错误信息

  1. 1 <?php
  2. 2 /**
  3. 3 * Created by PhpStorm.
  4. 4 * User: Haima
  5. 5 * Date: 2018/7/12
  6. 6 * Time: 3:11
  7. 7 */
  8. 8
  9. 9 namespace app\lib\exception;
  10. 10 use Exception;
  11. 11 use think\exception\Handle;
  12. 12 use think\Log;
  13. 13 use think\Request;
  14. 14
  15. 15 class ExceptionHandler extends Handle
  16. 16 {
  17. 17 private $code;
  18. 18 private $msg;
  19. 19 private $errorCode;
  20. 20
  21. 21 public function render(Exception $e)
  22. 22 {
  23. 23 if($e instanceof BaseException){
  24. 24 //如果是自定义异常,则控制http状态码,不需要记录日志
  25. 25 //因为这些通常是因为客户端传递参数错误或者是用户请求造成的异常
  26. 26 //不应当记录日志
  27. 27 //这里取的是当前抛出异常的控制器里定义的异常信息
  28. 28 $this->code = $e->code;
  29. 29 $this->msg = $e->msg;
  30. 30 $this->errorCode = $e->errorCode;
  31. 31 }
  32. 32 else{
  33. 33 // 如果是服务器未处理的异常,将http状态码设置为500,并记录日志
  34. 34 //Config::get('app_debug'); //获取config.php里的配置信息
  35. 35 if (config('app_debug')){ //获取config.php里的配置信息如果是true走这里
  36. 36 // 如果是前台调适人员看就显示json格式错误
  37. 37 // 调试状态下需要显示TP默认的异常页面,因为TP的默认就是页面
  38. 38 // 很容易看出问题
  39. 39 return parent::render($e); //调用thinkphp5默认的报错页面
  40. 40 }
  41. 41 //如果是后台调适人员看就显示json格式错误
  42. 42 $this->code = 500;
  43. 43 $this->msg = '服务器错误,不想给你看';
  44. 44 $this->errorCode = 999;
  45. 45 $this->recordErrorLog($e); //调用服务器异常错误
  46. 46 }
  47. 47 $request = Request::instance();
  48. 48 $result = array(
  49. 49 'msg' => $this->msg,
  50. 50 'error_code' => $this->errorCode,
  51. 51 'request_url' => $request->url()
  52. 52 );
  53. 53 return json($result,$this->code);
  54. 54 }
  55. 55
  56. 56 //服务器异常错误
  57. 57 private function recordErrorLog(Exception $e){
  58. 58 Log::init([
  59. 59 'type'=>'File', //生成的类型是文件
  60. 60 'path'=>LOG_PATH, //日志生成的路径
  61. 61 'level'=>['error'] // 日志记录级别,使用数组表示
  62. 62 ]);
  63. 63 Log::record($e->getMessage(),'error'); //写入日志
  64. 64 }
  65. 65 }

访问结果:

报出的就是validate里定义的错误信息

$code 和 $errorCode 就是 parameterException里定义的信息


6-9 全局异常处理的应用 中 12:04

异常处理优化代码:

思路:

parameterException继承了BaseException,所以它自然也继承了父类里的__construct构造函数,

BaseValidate里实例化parameterException,并通过传参给,parameterException里的__construct构造函数重写了parameterException里的$msg属性,

ExceptionHandler里判断异常后,抛出异常时取的是当前被抛出异常的 parameterException里的$msg属性信息.

BaseValidate里:

  1. 1 <?php
  2. 2 /**
  3. 3 * Created by PhpStorm.
  4. 4 * User: Administrator
  5. 5 * Date: 2018/7/10
  6. 6 * Time: 21:49
  7. 7 */
  8. 8
  9. 9 namespace app\api\validate;
  10. 10
  11. 11 use app\lib\exception\parameterException;
  12. 12 use think\Exception;
  13. 13 use think\Request;
  14. 14 use think\Validate;
  15. 15
  16. 16 class BaseValidate extends Validate
  17. 17 {
  18. 18
  19. 19 //所有的整个参数验证层的错误处理都集中在这里,承担了所有验证层的验证工作
  20. 20 public function goCheck()
  21. 21 {
  22. 22 //获取http传入的参数
  23. 23 //方法一:
  24. 24 // $request = Request::instance();
  25. 25 // $params = $request->param();
  26. 26 // 方法二:
  27. 27 $params = Request::instance()->param();
  28. 28 //对参数进行校验
  29. 29 if(!$this->check($params)){
  30. 30
  31. 31 //优化下面的代码,实例化时调用传入参数重写parameterException下的$msg属性
  32. 32 //而不用$e->msg=$this->error;这样的方式重写
  33. 33 $e = new parameterException([
  34. 34 'msg'=>$this->error //只改写msg 其它两个值还用原始值
  35. 35 ]);
  36. 36
  37. 37 throw $e; //优势,只管抛出异常,异常的类型交由ExceptionHandler来判断,然后决定抛出什么样的异常
  38. 38
  39. 39 }
  40. 40 else{
  41. 41 return true;
  42. 42 }
  43. 43 }
  44. 44 }

BaseException里:

  1. 1 <?php
  2. 2 /**
  3. 3 * Created by Haima.
  4. 4 * Author:Haima
  5. 5 * QQ:228654416
  6. 6 * Date: 2018/7/12
  7. 7 * Time: 20:49
  8. 8 */
  9. 9
  10. 10 namespace app\lib\exception;
  11. 11
  12. 12 use think\Exception;
  13. 13
  14. 14 class BaseException extends Exception
  15. 15 {
  16. 16 //HTTP 状态码 404,200
  17. 17 public $code = 400;
  18. 18
  19. 19 //错误的具体信息
  20. 20 public $msg = '参数错误';
  21. 21
  22. 22 //自定义的错误码
  23. 23 public $errorCode = 10000;
  24. 24
  25. 25 public function __construct($param = []){
  26. 26 if (!is_array($param)){
  27. 27 //下面两种处理方式都可以,看个人怎么理解了.
  28. 28 //方法一:如果传来的不是数组就返回回去,认为不是要改写属性
  29. 29 return;
  30. 30 //方法二: 如果不是数组就报错,强制让传入数组
  31. 31 // throw new Exception('参数必需是数组');
  32. 32 }
  33. 33 if(array_key_exists('code',$param)){
  34. 34 $this->code = $param['code'];
  35. 35 }
  36. 36
  37. 37 if(array_key_exists('msg',$param)){
  38. 38 $this->msg = $param['msg'];
  39. 39 }
  40. 40
  41. 41 if(array_key_exists('errorCode',$param)){
  42. 42 $this->errorCode = $param['error'];
  43. 43 }
  44. 44 }
  45. 45 }

parameterException里:

  1. 1 <?php
  2. 2 /**
  3. 3 * Created by Haima.
  4. 4 * Author:Haima
  5. 5 * QQ:228654416
  6. 6 * Date: 2018/7/15
  7. 7 * Time: 10:48
  8. 8 */
  9. 9
  10. 10 namespace app\lib\exception;
  11. 11
  12. 12
  13. 13 use think\Exception;
  14. 14
  15. 15 class parameterException extends BaseException
  16. 16 {
  17. 17 public $code = 400;
  18. 18 //随便定义一个通用的提示信息,之后validate抛出异常信息时,会被重写成validate里定义的错误信息
  19. 19 public $msg = '参数错误';
  20. 20 //通过参数错误,凡是被验证层检查出来的错误都返回一个10000
  21. 21 public $errorCode = 10000;
  22. 22
  23. 23
  24. 24 }

ExceptionHandler里判断并抛出异常

访问结果:


6-10 全局异常处理的应用 下 04:16

优化代码:

修改BaseValidate里加上batch(),命苦支持批量验证

IDMustBePosttiveInt里再加入num的验证

访问一下:

z.com/banner/0.1?num=4


6-11 本章小结与AOP思想 12:56

1.构建统一的业务处理层(如验证层,异常处理层).

2.努力重构,写出更优秀的代码

3.AOP面向切面编程:

不要把代码写的太直白,要站在一个更高的角度,用比较抽象的方式,统一的总体的来处理处某一个问题,

举个例子:

AOP思想,就相当于电影院里的检票员检票的流程,只有一个检票口,每个来看电影的人统一在检票口进行检票,这样就很节省资源了.

唯一的入口,统一的检票处理.

第6章 AOP与全局异常处理6.5-6.11 慕课网微信小程序开发学习笔记的更多相关文章

  1. 第6章 AOP与全局异常处理6.1-6.4 慕课网微信小程序开发学习笔记

    第6章 AOP与全局异常处理 https://coding.imooc.com/learn/list/97.html 目录: 第6章 AOP与全局异常处理6-1 正确理解异常处理流程 13:236-2 ...

  2. 第1-5章 慕课网微信小程序开发学习笔记

    第1章 前言:不同的时代,不同的Web --微信小程序商城构建全栈应用 http://note.youdao.com/noteshare?id=a0e9b058853dbccf886c1a890594 ...

  3. 第7章 数据库访问与ORM 慕课网微信小程序开发学习笔记

    第7章 数据库访问与ORM https://coding.imooc.com/learn/list/97.html 目录: 7-1 数据库操作三种方式之原生SQL 19:09 7-2 从一个错误了解E ...

  4. 【微信小程序开发】全局配置

    今天看看小程序全局配置. 上一篇[微信小程序开发]秒懂,架构及框架 配置,无非就是为了增加框架的灵活性,而定下的规则. 微信小程序的配置文件是一个树状结构,各个节点代表不同的配置项,小程序框架会解析这 ...

  5. 微信小程序开发系列(二)小程序的全局文件

    其实你已经知道了小程序的文件结构 上一节讲到,小程序的页面由三部分组成: 视图(.wxml).逻辑(.js).样式(.wxss). 我们这次重新展开文件结构: 小程序用到的文件类型只有四种,正如你所看 ...

  6. 微信小程序开发——全局配置详细介绍

    本文针对官方文档未说明清楚的进行详细探索研究,官方文档详见:全局配置 . pages: 删除页面,需要先删除app.json中pages对应页面的路径,再去删除页面相关的所有文件,不然会出现页面文件混 ...

  7. 微信小程序开发——连续快速点击按钮调用小程序api返回后仍然自动重新调用的异常处理

    前言: 小程序开发中诸如获取用户手机号码.调起微信支付.领取卡券等api都是会有一定的延迟的.也就是说通过点击按钮调用这些api的时候,从点击按钮调用api,到支付页面或者领取卡券界面展示出来是需要一 ...

  8. 微信小程序 如何定义全局函数?

    微信小程序 定义全局数据.函数复用.模版等 微信小程序定义全局数据.函数复用.模版等问题总结: 1.如何定义全局数据 在app.js的App({})中定义的数据或函数都是全局的,在页面中可以通过var ...

  9. 微信小程序学习笔记(二)--框架-全局及页面配置

    描述和功能 框架提供了自己的视图层描述语言 WXML 和 WXSS,以及基于 JavaScript 的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑. 响应的数 ...

随机推荐

  1. Vue实例生命周期+vueRoter

    Vue实例生命周期 vue生命周期之beforeCreate 实例创建之前除标签外,所有的vue需要的数据,事件都不存在 vue生命周期之created 实例创建之后,data和事件已经被解析到,el ...

  2. 基于apache httpclient的常用接口调用方法

    现在的接口开发,大部分是基于http的请求和处理,现在整理了一份常用的调用方式工具类 package com.xh.oms.common.util; import java.io.BufferedRe ...

  3. NET Core项目部署

    NET Core项目部署到linux(Centos7) 阅读目录 1.开篇说明 2.Jexus简单说明 3.Visual Studio 2015本地发布并且测试 4.配置Jexus并且部署.NET C ...

  4. JavaSE---jar文件

    1.当一个应用程序开发完成后,大致有3种方式发布: 1.1 使用平台相关的编译器将整个应用编译成平台相关的可执行文件: 1.2 为整个应用编辑一个批处理文件: 1.3 将应用程序制作为一个可执行的ja ...

  5. 去掉 Ctrl + A 全选

    import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.table.*; public ...

  6. (转)linux实战考试题:批量创建用户和密码-看看你会么?

    老男孩教育第五关实战考试题:批量创建10个用户stu01-stu10,并且设置随机8位密码,要求不能用shell的循环(例如:for,while等),只能用linux命令及管道实现. 方法1:[roo ...

  7. Kendo MVVM (二) ObservableObject 对象

    概述 Kendo MVVM 框架关键的一个部分为 ViewModel,它主要是通过 kendo.data.ObserableObject 来提供支持的.它可以监控改变( UI 变化或是值的变化)并通知 ...

  8. 动态加载sd卡或者手机内置存储卡的so库

    package com.wsc.utils; import android.content.Context; import com.wsc.common.Entrance; import com.ws ...

  9. Linux shell标准输入,标准输出,错误输出

    shell中可能经常能看到:1>/dev/null  2>&1  eg:sudo kill -9 `ps -elf |grep -v grep|grep $1|awk '{prin ...

  10. PHP针对二维数组无限遍历变形研究

    一.需要变形的二维数组 $arr = Array( Array ( 'material_id' => 1, 'material_name' => '铜板纸', 'parent_id' =& ...