Skip to content
This repository was archived by the owner on Jan 23, 2019. It is now read-only.

Commit 95f78bc

Browse files
committed
up
1 parent b2ab2a4 commit 95f78bc

File tree

3 files changed

+190
-20
lines changed

3 files changed

+190
-20
lines changed

src/Components/ErrorHandler.php

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Inhere\Library\Components;
1313

14+
use Inhere\Library\Helpers\Obj;
1415
use Inhere\Library\Helpers\PhpHelper;
1516
use Monolog\Logger;
1617
use Psr\Log\LoggerInterface;
@@ -28,7 +29,7 @@
2829
*/
2930
class ErrorHandler
3031
{
31-
private $logger;
32+
protected $logger;
3233

3334
private $previousExceptionHandler;
3435
private $uncaughtExceptionLevel;
@@ -38,16 +39,21 @@ class ErrorHandler
3839
private $handleOnlyReportedErrors;
3940

4041
private $hasFatalErrorHandler;
41-
private $fatalLevel;
42-
private $reservedMemory;
43-
private static $fatalErrors = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
42+
protected $fatalLevel;
43+
protected $reservedMemory;
44+
public static $fatalErrors = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
45+
46+
private $exitOnHandled = true;
4447

4548
/**
4649
* ErrorHandler constructor.
4750
* @param LoggerInterface $logger
51+
* @param array $options
4852
*/
49-
public function __construct(LoggerInterface $logger)
53+
public function __construct(LoggerInterface $logger, array $options = [])
5054
{
55+
Obj::smartConfigure($this, $options);
56+
5157
$this->logger = $logger;
5258
}
5359

@@ -79,29 +85,45 @@ class_exists(LogLevel::class);
7985
return $this;
8086
}
8187

88+
/**
89+
* @param null $level
90+
* @param bool $callPrevious
91+
*/
8292
public function registerExceptionHandler($level = null, $callPrevious = true)
8393
{
84-
$prev = set_exception_handler(array($this, 'handleException'));
94+
$prev = set_exception_handler([$this, 'handleException']);
8595
$this->uncaughtExceptionLevel = $level;
96+
8697
if ($callPrevious && $prev) {
8798
$this->previousExceptionHandler = $prev;
8899
}
89100
}
90101

91-
public function registerErrorHandler(array $levelMap = array(), $callPrevious = true, $errorTypes = -1, $handleOnlyReportedErrors = true)
102+
/**
103+
* @param array $levelMap
104+
* @param bool $callPrevious
105+
* @param int $errorTypes
106+
* @param bool $handleOnlyReportedErrors
107+
*/
108+
public function registerErrorHandler(array $levelMap = [], $callPrevious = true, $errorTypes = -1, $handleOnlyReportedErrors = true)
92109
{
93-
$prev = set_error_handler(array($this, 'handleError'), $errorTypes);
110+
$prev = set_error_handler([$this, 'handleError'], $errorTypes);
94111
$this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap);
112+
95113
if ($callPrevious) {
96114
$this->previousErrorHandler = $prev ?: true;
97115
}
98116

99117
$this->handleOnlyReportedErrors = $handleOnlyReportedErrors;
100118
}
101119

120+
/**
121+
* @param null $level
122+
* @param int $reservedMemorySize
123+
*/
102124
public function registerFatalHandler($level = null, $reservedMemorySize = 20)
103125
{
104-
register_shutdown_function(array($this, 'handleFatalError'));
126+
register_shutdown_function([$this, 'handleFatalError']);
105127

106128
$this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize);
107129
$this->fatalLevel = $level;
@@ -130,22 +152,23 @@ protected function defaultErrorLevelMap()
130152
}
131153

132154
/**
133-
* @private
134155
* @param \Throwable $e
135156
*/
136157
public function handleException($e)
137158
{
138159
$this->logger->log(
139160
$this->uncaughtExceptionLevel ?? LogLevel::ERROR,
140161
sprintf('Uncaught Exception %s: "%s" at %s line %s', get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()),
141-
array('exception' => $e)
162+
['exception' => $e]
142163
);
143164

144165
if ($this->previousExceptionHandler) {
145166
PhpHelper::call($this->previousExceptionHandler, $e);
146167
}
147168

148-
exit(255);
169+
if ($this->exitOnHandled) {
170+
exit(255);
171+
}
149172
}
150173

151174
/**
@@ -166,21 +189,28 @@ public function handleError($code, $message, $file = '', $line = 0, array $conte
166189
// fatal error codes are ignored if a fatal error handler is present as well to avoid duplicate log entries
167190
if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) {
168191
$level = $this->errorLevelMap[$code] ?? LogLevel::CRITICAL;
169-
$this->logger->log($level, self::codeToString($code).': '.$message, array('code' => $code, 'message' => $message, 'file' => $file, 'line' => $line));
192+
$this->logger->log($level, self::codeToString($code).': '.$message, [
193+
'code' => $code,
194+
'message' => $message,
195+
'file' => $file,
196+
'line' => $line,
197+
'catcher' => __METHOD__,
198+
]);
170199
}
171200

172201
if ($this->previousErrorHandler === true) {
173202
return false;
174203
}
175204

176205
if ($this->previousErrorHandler) {
177-
return call_user_func($this->previousErrorHandler, $code, $message, $file, $line, $context);
206+
return PhpHelper::call($this->previousErrorHandler, [$code, $message, $file, $line, $context]);
178207
}
179208

180209
return false;
181210
}
182211

183212
/**
213+
* handleFatalError
184214
* @private
185215
*/
186216
public function handleFatalError()
@@ -192,7 +222,12 @@ public function handleFatalError()
192222
$this->logger->log(
193223
$this->fatalLevel ?? LogLevel::ALERT,
194224
'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'],
195-
array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'])
225+
[
226+
'code' => $lastError['type'],
227+
'message' => $lastError['message'],
228+
'file' => $lastError['file'],
229+
'line' => $lastError['line']
230+
]
196231
);
197232

198233
if ($this->logger instanceof Logger) {
@@ -205,7 +240,7 @@ public function handleFatalError()
205240
}
206241
}
207242

208-
private static function codeToString($code)
243+
public static function codeToString($code)
209244
{
210245
switch ($code) {
211246
case E_ERROR:
@@ -242,4 +277,20 @@ private static function codeToString($code)
242277

243278
return 'Unknown PHP error';
244279
}
280+
281+
/**
282+
* @return bool
283+
*/
284+
public function isExitOnHandled(): bool
285+
{
286+
return $this->exitOnHandled;
287+
}
288+
289+
/**
290+
* @param bool $exitOnHandled
291+
*/
292+
public function setExitOnHandled($exitOnHandled)
293+
{
294+
$this->exitOnHandled = (bool)$exitOnHandled;
295+
}
245296
}

src/Helpers/PhpError.php

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
/**
3+
* Created by PhpStorm.
4+
* User: inhere
5+
* Date: 2017/10/15
6+
* Time: 上午10:04
7+
*/
8+
9+
namespace Inhere\Library\Helpers;
10+
11+
/**
12+
* Class PhpError
13+
* @package Inhere\Library\Helpers
14+
*/
15+
class PhpError
16+
{
17+
/** @var array */
18+
public static $fatalErrors = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
19+
20+
/**
21+
* $lastError = error_get_last();
22+
* @param array $lastError
23+
* @return array
24+
*/
25+
public static function toArray(array $lastError, $catcher = null)
26+
{
27+
$digest = 'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'];
28+
$data = [
29+
'code' => $lastError['type'],
30+
'message' => $lastError['message'],
31+
'file' => $lastError['file'],
32+
'line' => $lastError['line'],
33+
'catcher' => __METHOD__,
34+
];
35+
36+
if ($catcher) {
37+
$data['catcher'] = $catcher;
38+
}
39+
40+
return [$digest, $data];
41+
}
42+
43+
/**
44+
* @param int $code
45+
* @return string
46+
*/
47+
public static function codeToString(int $code)
48+
{
49+
switch ($code) {
50+
case E_ERROR:
51+
return 'E_ERROR';
52+
case E_WARNING:
53+
return 'E_WARNING';
54+
case E_PARSE:
55+
return 'E_PARSE';
56+
case E_NOTICE:
57+
return 'E_NOTICE';
58+
case E_CORE_ERROR:
59+
return 'E_CORE_ERROR';
60+
case E_CORE_WARNING:
61+
return 'E_CORE_WARNING';
62+
case E_COMPILE_ERROR:
63+
return 'E_COMPILE_ERROR';
64+
case E_COMPILE_WARNING:
65+
return 'E_COMPILE_WARNING';
66+
case E_USER_ERROR:
67+
return 'E_USER_ERROR';
68+
case E_USER_WARNING:
69+
return 'E_USER_WARNING';
70+
case E_USER_NOTICE:
71+
return 'E_USER_NOTICE';
72+
case E_STRICT:
73+
return 'E_STRICT';
74+
case E_RECOVERABLE_ERROR:
75+
return 'E_RECOVERABLE_ERROR';
76+
case E_DEPRECATED:
77+
return 'E_DEPRECATED';
78+
case E_USER_DEPRECATED:
79+
return 'E_USER_DEPRECATED';
80+
}
81+
82+
return 'Unknown PHP error';
83+
}
84+
}

src/Helpers/PhpException.php

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,33 @@ public static function toHtml($e, $getTrace = true, $catcher = null, $clearHtml
5757
return $message;
5858
}
5959

60+
/**
61+
* Converts an exception into a simple array.
62+
* @param \Exception|\Throwable $e the exception being converted
63+
* @param bool $getTrace
64+
* @param null|string $catcher
65+
* @return array
66+
*/
67+
public static function toArray($e, $getTrace = true, $catcher = null)
68+
{
69+
$data = [
70+
'class' => get_class($e),
71+
'message' => $e->getMessage(),
72+
'code' => $e->getCode(),
73+
'file' => $e->getFile().':'.$e->getLine(),
74+
];
75+
76+
if ($catcher) {
77+
$data['catcher'] = $catcher;
78+
}
79+
80+
if ($getTrace) {
81+
$data['trace'] = $e->getTrace();
82+
}
83+
84+
return $data;
85+
}
86+
6087
/**
6188
* Converts an exception into a json string.
6289
* @param \Exception|\Throwable $e the exception being converted
@@ -67,21 +94,29 @@ public static function toHtml($e, $getTrace = true, $catcher = null, $clearHtml
6794
public static function toJson($e, $getTrace = true, $catcher = null)
6895
{
6996
if (!$getTrace) {
70-
$message = "Error: {$e->getMessage()}";
97+
$message = json_encode(['msg' => "Error: {$e->getMessage()}"]);
7198
} else {
7299
$map = [
73100
'code' => $e->getCode() ?: 500,
74101
'msg' => sprintf(
75-
'%s(%d): %s, File: %s(Line %d)%s',
102+
'%s(%d): %s, File: %s(Line %d)',
76103
get_class($e),
77104
$e->getCode(),
78105
$e->getMessage(),
79106
$e->getFile(),
80-
$e->getLine(),
81-
$catcher ? ", Catch By: $catcher" : ''
107+
$e->getLine()
82108
),
83109
'data' => $e->getTrace()
84110
];
111+
112+
if ($catcher) {
113+
$map['catcher'] = $catcher;
114+
}
115+
116+
if ($getTrace) {
117+
$map['trace'] = $e->getTrace();
118+
}
119+
85120
$message = json_encode($map);
86121
}
87122

0 commit comments

Comments
 (0)