Laravel异常讲解

1.应用文件
bootstrap\app.php
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
2.内核请求处理
Illuminate\Foundation\Http\Kernel
use Illuminate\Contracts\Debug\ExceptionHandler;
public function handle($request)
{
try {
$request->enableHttpMethodParameterOverride();
$response = $this->sendRequestThroughRouter($request);
} catch (Exception $e) {
$this->reportException($e);
$response = $this->renderException($request, $e);
} catch (Throwable $e) {
$this->reportException($e = new FatalThrowableError($e));
$response = $this->renderException($request, $e);
}
$this->app['events']->dispatch(
new Events\RequestHandled($request, $response)
);
return $response;
}
protected function renderException($request, Exception $e)
{
return $this->app[ExceptionHandler::class]->render($request, $e);
}
protected function sendRequestThroughRouter($request)
{
$this->app->instance('request', $request);
Facade::clearResolvedInstance('request');
$this->bootstrap();
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
}
public function bootstrap()
{
if (! $this->app->hasBeenBootstrapped()) {
$this->app->bootstrapWith($this->bootstrappers());
}
}
protected $bootstrappers = [
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
\Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
\Illuminate\Foundation\Bootstrap\RegisterFacades::class,
\Illuminate\Foundation\Bootstrap\RegisterProviders::class,
\Illuminate\Foundation\Bootstrap\BootProviders::class,
];
3.应用容器
Illuminate\Foundation\Application
public function bootstrapWith(array $bootstrappers)
{
$this->hasBeenBootstrapped = true;
foreach ($bootstrappers as $bootstrapper) {
$this['events']->dispatch('bootstrapping: '.$bootstrapper, [$this]);
$this->make($bootstrapper)->bootstrap($this);
$this['events']->dispatch('bootstrapped: '.$bootstrapper, [$this]);
}
}
4.启动绑定异常监听
Illuminate\Foundation\Bootstrap\HandleExceptions
use Illuminate\Contracts\Debug\ExceptionHandler;
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);
}
}
public function handleShutdown()
{
if (! is_null($error = error_get_last()) && $this->isFatal($error['type'])) {
$this->handleException($this->fatalExceptionFromError($error, 0));
}
}
protected function getExceptionHandler()
{
return $this->app->make(ExceptionHandler::class);
}
5.管道处理(中间件)
Illuminate\Pipeline\Pipeline
public function then(Closure $destination)
{
$pipeline = array_reduce(
array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
);
return $pipeline($this->passable);
}
Illuminate\Routing\Pipeline
protected function prepareDestination(Closure $destination)
{
return function ($passable) use ($destination) {
try {
return $destination($passable);
} catch (Exception $e) {
return $this->handleException($passable, $e);
} catch (Throwable $e) {
return $this->handleException($passable, new FatalThrowableError($e));
}
};
}
protected function carry()
{
return function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
try {
$slice = parent::carry();
$callable = $slice($stack, $pipe);
return $callable($passable);
} catch (Exception $e) {
return $this->handleException($passable, $e);
} catch (Throwable $e) {
return $this->handleException($passable, new FatalThrowableError($e));
}
};
};
}
6.路由处理
Illuminate\Routing\Router
protected function runRouteWithinStack(Route $route, Request $request)
{
$shouldSkipMiddleware = $this->container->bound('middleware.disable') &&
$this->container->make('middleware.disable') === true;
$middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddleware($route);
return (new Pipeline($this->container))
->send($request)
->through($middleware)
->then(function ($request) use ($route) {
return $this->prepareResponse(
$request, $route->run()
);
});
}
7.中间件伪代码
7.1全局中间件
$middleware = [
\App\Http\Middleware\CrossDomain::class,
\App\Http\Middleware\RequestLog::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
];
function () : CrossDomain
{
function () : RequestLog
{
function () : CheckForMaintenanceMode
{
function () : ValidatePostSize
{
function () : TrimStrings
{
function () : ConvertEmptyStringsToNull
{
function () : TrustProxies
{
return $this->dispatchToRouter();
} ()
} ()
} ()
} ()
} ()
} ()
} ()
7.2路由中间件
$middlewareGroups = [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\CheckLogin::class,
\App\Http\Middleware\FormatOutput::class,
]
function () : EncryptCookies
{
function () : AddQueuedCookiesToResponse
{
function () : StartSession
{
function () : SubstituteBindings
{
function () : CheckLogin
{
function () : FormatOutput
{
return $this->prepareResponse(
$request, $route->run()
);
} ()
} ()
} ()
} ()
} ()
} ()
7.3前置操作or后置操作
function ()
{
function ()
{
$response = function () {
} ();
return $response;
} ()
} ()
8.最终链条
try {
try {
} catch (Exception $e) {
try {
try {
} catch (Exception $e) {
} catch (Throwable $e) {
}
} catch (Exception $e) {
} catch (Throwable $e) {
}
} catch (Throwable $e) {
}
} catch (Exception $e) {
} catch (Throwable $e) {
}