ExceptionHandle.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. <?php
  2. namespace app;
  3. use think\db\exception\DataNotFoundException;
  4. use think\db\exception\ModelNotFoundException;
  5. use think\exception\Handle;
  6. use think\exception\HttpException;
  7. use think\exception\HttpResponseException;
  8. use think\exception\ValidateException;
  9. use think\Response;
  10. use think\Request;
  11. use Throwable;
  12. /**
  13. * 应用异常处理类
  14. */
  15. class ExceptionHandle extends Handle
  16. {
  17. /**
  18. * 不需要记录信息(日志)的异常类列表
  19. * @var array
  20. */
  21. protected $ignoreReport = [
  22. HttpException::class,
  23. HttpResponseException::class,
  24. ModelNotFoundException::class,
  25. DataNotFoundException::class,
  26. ValidateException::class,
  27. ];
  28. /**
  29. * 记录异常信息(包括日志或者其它方式记录)
  30. *
  31. * @access public
  32. * @param Throwable $exception
  33. * @return void
  34. */
  35. public function report(Throwable $exception): void
  36. {
  37. // 使用内置的方式记录异常日志
  38. parent::report($exception);
  39. }
  40. /**
  41. * Render an exception into an HTTP response.
  42. *
  43. * @access public
  44. * @param Request $request
  45. * @param Throwable $e
  46. * @return Response
  47. */
  48. public function render(Request $request, Throwable $e): Response
  49. {
  50. // 添加自定义异常处理机制
  51. // 其他错误交给系统处理
  52. return parent::render($request, $e);
  53. }
  54. /**
  55. * 收集异常数据
  56. */
  57. protected function convertExceptionToArray(Throwable $exception): array
  58. {
  59. if ($this->app->isDebug()) {
  60. // 调试模式,获取详细的错误信息
  61. $traces = [];
  62. $nextException = $exception;
  63. do {
  64. $traces[] = [
  65. 'name' => $nextException::class,
  66. 'file' => $nextException->getFile(),
  67. 'line' => $nextException->getLine(),
  68. 'code' => $this->getCode($nextException),
  69. 'message' => $this->getMessage($nextException),
  70. 'trace' => $nextException->getTrace(),
  71. 'source' => $this->getSourceCode($nextException),
  72. ];
  73. } while ($nextException = $nextException->getPrevious());
  74. // 循环引用检测并直接置空 traces(比起循环引用导致的报错,置空后开发者能得到更多真实的错误信息)
  75. if ($this->app->request->isJson()) {
  76. $json = json_encode($traces, JSON_UNESCAPED_UNICODE);
  77. if (false === $json && in_array(json_last_error(), [JSON_ERROR_DEPTH, JSON_ERROR_RECURSION])) {
  78. $traces = [];
  79. }
  80. }
  81. $data = [
  82. 'code' => $this->getCode($exception),
  83. 'message' => $this->getMessage($exception),
  84. 'traces' => $traces,
  85. 'datas' => $this->getExtendData($exception),
  86. 'tables' => [
  87. 'GET Data' => $this->app->request->get(),
  88. 'POST Data' => $this->app->request->post(),
  89. 'Files' => $this->app->request->file(),
  90. 'Cookies' => $this->app->request->cookie(),
  91. 'Session' => $this->app->exists('session') ? $this->app->session->all() : [],
  92. 'Server/Request Data' => $this->app->request->server(),
  93. ],
  94. ];
  95. } else {
  96. // 部署模式仅显示 Code 和 Message
  97. $data = [
  98. 'code' => $this->getCode($exception),
  99. 'message' => $this->getMessage($exception),
  100. ];
  101. if (!$this->app->config->get('app.show_error_msg')) {
  102. // 不显示详细错误信息
  103. $data['message'] = $this->app->config->get('app.error_message');
  104. }
  105. }
  106. return $data;
  107. }
  108. }