zm
2021-03-25 d84ff6053b22269a6c59dc005e9efb8de6595988
commit | author | age
90c639 1 <?php
Z 2 /**
3  * @copyright ©2018 浙江禾匠信息科技
4  * @author Lu Wei
5  * @link http://www.zjhejiang.com/
6  * Created by IntelliJ IDEA
7  * Date Time: 2018/10/30 12:00
8  */
9
10
11 namespace app\core;
12
13
14 use app\models\CoreExceptionLog;
15 use yii\web\Response;
16
17 class ErrorHandler extends \yii\web\ErrorHandler
18 {
19     public function init()
20     {
21         parent::init();
22         if (!YII_DEBUG) {
23             $this->exceptionView = '@app/views/error/exception.php';
24             $this->errorView = '@app/views/error/error.php';
25         }
26     }
27
28     /**
29      * @param \Exception $exception
30      * @return array
31      */
32     private function formatException($exception)
33     {
34         $title = $exception->getMessage();
35         $title = str_replace('\\\\', '\\', $title);
36         $file = $exception->getFile();
37         $file = str_replace('\\', '/', $file);
38         $line = $exception->getLine();
39         $list = $exception->getTrace();
40         $newList = [
41             "#{$line}: {$file}",
42         ];
43         foreach ($list as $i => $item) {
44             if ($i === 0) {
45                 continue;
46             }
47             if (isset($item['file'])) {
48                 $file = $item['file'];
49                 $file = str_replace('\\', '/', $file);
50                 $newList[] = "#{$item['line']}: {$file}";
51             } elseif (isset($item['class'])) {
52                 $class = $item['class'];
53                 $class = str_replace('\\', '\\', $class);
54                 $newList[] = "#0: {$class}->{$item['function']}()";
55             }
56         }
57         return [
58             'title' => $title,
59             'list' => $newList,
60         ];
61     }
62
63     public function handleException($exception)
64     {
65         $this->exception = $exception;
66
67         // 记录日志
68         $errors = $this->getResult();
69         $log = new ExceptionLog();
70         $log->error($errors['title'], $errors['list']);
71
72         if (YII_DEBUG) {
73             return parent::handleException($exception);
74         } else {
75             if (\Yii::$app->has('response')) {
76                 $response = \Yii::$app->getResponse();
77             } else {
78                 $response = new Response();
79             }
80             if (\Yii::$app->request->isAjax) {
81                 $result = $this->getResult();
82                 $response->data = [
83                     'code' => 500,
84                     'msg' => $result['title'],
85                     'data' => null,
86                     'error' => $result['list'],
87                 ];
88             } else {
89                 $response->data = $this->renderFile($this->exceptionView, [
90                     'handler' => $this,
91                 ]);
92             }
93             $response->send();
94         }
95     }
96
97     public function handleError($code, $message, $file, $line)
98     {
99         return parent::handleError($code, $message, $file, $line);
100     }
101
102     public function getResult()
103     {
104         return $this->formatException($this->exception);
105     }
106
107     /**
108      * Renders call stack.
109      * @param \Exception|\ParseError $exception exception to get call stack from
110      * @return string HTML content of the rendered call stack.
111      * @since 2.0.12
112      */
113     public function renderCallStack($exception)
114     {
115         $out = '<ul>';
116         $out .= $this->renderCallStackItem($exception->getFile(), $exception->getLine(), null, null, [], 1);
117         for ($i = 0, $trace = $exception->getTrace(), $length = count($trace); $i < $length; ++$i) {
118             $file = !empty($trace[$i]['file']) ? $trace[$i]['file'] : null;
119             $line = !empty($trace[$i]['line']) ? $trace[$i]['line'] : null;
120             $class = !empty($trace[$i]['class']) ? $trace[$i]['class'] : null;
121             $function = null;
122             if (!empty($trace[$i]['function']) && $trace[$i]['function'] !== 'unknown') {
123                 $function = $trace[$i]['function'];
124             }
125             // 不输出函数方法参数内容
126             // $args = !empty($trace[$i]['args']) ? $trace[$i]['args'] : [];
127             $args = [];
128             $out .= $this->renderCallStackItem($file, $line, $class, $function, $args, $i + 2);
129         }
130         $out .= '</ul>';
131         return $out;
132     }
133 }