|
|
<?php |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace think; |
|
|
|
|
|
use think\console\Output as ConsoleOutput; |
|
|
use think\exception\ErrorException; |
|
|
use think\exception\Handle; |
|
|
use think\exception\ThrowableError; |
|
|
|
|
|
class Error |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function register() |
|
|
{ |
|
|
error_reporting(E_ALL); |
|
|
set_error_handler([__CLASS__, 'appError']); |
|
|
set_exception_handler([__CLASS__, 'appException']); |
|
|
register_shutdown_function([__CLASS__, 'appShutdown']); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function appException($e) |
|
|
{ |
|
|
if (!$e instanceof \Exception) { |
|
|
$e = new ThrowableError($e); |
|
|
} |
|
|
|
|
|
$handler = self::getExceptionHandler(); |
|
|
$handler->report($e); |
|
|
|
|
|
if (IS_CLI) { |
|
|
$handler->renderForConsole(new ConsoleOutput, $e); |
|
|
} else { |
|
|
$handler->render($e)->send(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function appError($errno, $errstr, $errfile = '', $errline = 0) |
|
|
{ |
|
|
$exception = new ErrorException($errno, $errstr, $errfile, $errline); |
|
|
|
|
|
|
|
|
if (error_reporting() & $errno) { |
|
|
throw $exception; |
|
|
} |
|
|
|
|
|
self::getExceptionHandler()->report($exception); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function appShutdown() |
|
|
{ |
|
|
|
|
|
if (!is_null($error = error_get_last()) && self::isFatal($error['type'])) { |
|
|
self::appException(new ErrorException( |
|
|
$error['type'], $error['message'], $error['file'], $error['line'] |
|
|
)); |
|
|
} |
|
|
|
|
|
|
|
|
Log::save(); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected static function isFatal($type) |
|
|
{ |
|
|
return in_array($type, [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE]); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function getExceptionHandler() |
|
|
{ |
|
|
static $handle; |
|
|
|
|
|
if (!$handle) { |
|
|
|
|
|
$class = Config::get('exception_handle'); |
|
|
|
|
|
if ($class && is_string($class) && class_exists($class) && |
|
|
is_subclass_of($class, "\\think\\exception\\Handle") |
|
|
) { |
|
|
$handle = new $class; |
|
|
} else { |
|
|
$handle = new Handle; |
|
|
|
|
|
if ($class instanceof \Closure) { |
|
|
$handle->setRender($class); |
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
return $handle; |
|
|
} |
|
|
} |
|
|
|