场景
分析
- laravel在完成了对环境变量 && 配置文件的初始化之后 就开始了对\Illuminate\Foundation\Bootstrap\HandleExceptions::class 的初始化,
测试
- error_reporting(-1);
- set_error_handler([$this, ‘handleError’]);
- 定义错误处理函数
if (error_reporting() & $level) { throw new ErrorException($message, 0, $level, $file, $line); }
将所错误转成ErrorException抛出
- set_exception_handler([$this, ‘handleException’]);
- 定义未捕获的异常处理函数
$this->getExceptionHandler()->report($e);
return $this->app->make(ExceptionHandler::class);
- 从容器中获取App\Exceptions\Handler::class 实例,然后调用对应的report方法
if ($this->shouldntReport($e)) {return;}
- 内部异常不进行处理
$logger = $this->container->make(LoggerInterface::class);
从容其中获取log实例
$logger->error( $e->getMessage(), array_merge($this->context(), ['exception' => $e]));
记录错误日志
总结
- laravel错误处理流程是 将php错误专成 exception,在自定义的expection中记录日志; 从而完成对框架的监控
源码 App\Exceptions\Handler::report
public function report(Exception $e)
{
if ($this->shouldntReport($e)) {
return;
}
if (method_exists($e, 'report')) {
return $e->report();
}
try {
$logger = $this->container->make(LoggerInterface::class);
} catch (Exception $ex) {
throw $e;
}
$logger->error(
$e->getMessage(),
array_merge($this->context(), ['exception' => $e]
));
}
源码(\Illuminate\Foundation\Bootstrap\HandleExceptions::class )
<?php
namespace Illuminate\Foundation\Bootstrap;
use Exception;
use ErrorException;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Contracts\Foundation\Application;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Debug\Exception\FatalErrorException;
use Symfony\Component\Debug\Exception\FatalThrowableError;
class HandleExceptions
{
protected $app;
public function bootstrap(Application $app)
{
$this->app = $app;
error_reporting(-1);
set_error_handler([$this, 'handleError']);
set_exception_handler([$this, 'handleException']);
register_shutdown_function([$this, 'handleShutdown']);
if (! $app->environment('testing')) {
ini_set('display_errors', 'Off');
}
}
public function handleError($level, $message, $file = '', $line = 0, $context = [])
{
if (error_reporting() & $level) {
throw new ErrorException($message, 0, $level, $file, $line);
}
}
public function handleException($e)
{
if (! $e instanceof Exception) {
$e = new FatalThrowableError($e);
}
try {
$this->getExceptionHandler()->report($e);
} catch (Exception $e) {
}
if ($this->app->runningInConsole()) {
$this->renderForConsole($e);
} else {
$this->renderHttpResponse($e);
}
}
protected function renderForConsole(Exception $e)
{
$this->getExceptionHandler()->renderForConsole(new ConsoleOutput, $e);
}
protected function renderHttpResponse(Exception $e)
{
$this->getExceptionHandler()->render($this->app['request'], $e)->send();
}
public function handleShutdown()
{
if (! is_null($error = error_get_last()) && $this->isFatal($error['type'])) {
$this->handleException($this->fatalExceptionFromError($error, 0));
}
}
protected function fatalExceptionFromError(array $error, $traceOffset = null)
{
return new FatalErrorException(
$error['message'], $error['type'], 0, $error['file'], $error['line'], $traceOffset
);
}
protected function isFatal($type)
{
return in_array($type, [E_COMPILE_ERROR, E_CORE_ERROR, E_ERROR, E_PARSE]);
}
protected function getExceptionHandler()
{
return $this->app->make(ExceptionHandler::class);
}
}