深入研究 Laravel 原始碼第四天

chonghua_123發表於2018-12-21

前言 單純學習

分析 index.php http核心,將傳入的請求傳送到http核心或控制檯核心,得到返回,終止請求

1、make(解析http控制檯例項)
2、handle(處理請求)
3、Illuminate\Http\Request::capture()
4、send
5、terminate

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
//解析這個抽象的例項,在bootstrap/app.php中有註冊單例App\Http\Kernel
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()//得到全域性表單請求例項
);處理請求得到響應
$response->send();//傳送響應
$kernel->terminate($request, $response)//終止請求

分析App\Http\Kernel 檔案

namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
    忽略
}

分析Illuminate\Foundation\Http\Kernel

1. 引入

use Exception;//異常
use Throwable;//異常與錯誤
use Illuminate\Routing\Router;//路由類
use Illuminate\Routing\Pipeline;//路由管道類
use Illuminate\Support\Facades\Facade;//門面抽象類
use Illuminate\Contracts\Debug\ExceptionHandler;//異常處理程式
use Illuminate\Contracts\Foundation\Application;//基礎應用介面
use Illuminate\Contracts\Http\Kernel as KernelContract;//基礎http核心介面
use Symfony\Component\Debug\Exception\FatalThrowableError;

2. 成員變數

class Kernel implements KernelContract
{
    //應用例項
    protected $app 
    //路由例項
    protected $router; 
    // 應用程式的引導類
    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,
    ];
    //中介軟體陣列
    protected $middleware = [];
    //中介軟體組陣列
    protected $middlewareGroups = [];
    //路由中介軟體
    protected $routeMiddleware = [];
    //*按優先順序排序的中介軟體列表
    protected $middlewarePriority = [
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \Illuminate\Auth\Middleware\Authenticate::class,
        \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Illuminate\Auth\Middleware\Authorize::class,
    ];

3 . 建構函式

    public function __construct(Application $app, Router $router)//依賴注入
    {
        $this->app = $app;   
        $this->router = $router;
        $router->middlewarePriority = $this->middlewarePriority;//按優先順序排序的中介軟體列表
        foreach ($this->middlewareGroups as $key => $middleware) {
            $router->middlewareGroup($key, $middleware);//新增路由中介軟體組
        }
        foreach ($this->routeMiddleware as $key => $middleware) {
            $router->aliasMiddleware($key, $middleware);//新增中介軟體別名
        }
    }

4. 處理傳入的HTTP請求

1、sendRequestThroughRouter

    public function handle($request)
    {
        try {
            //啟用_method請求引數的支援,以確定預期的HTTP方法
            $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;
    }

5. 通過中介軟體/路由器傳送給定的請求

1、bootstrap
2、Facade::clearResolvedInstance
3、send(設定通過管道傳送的物件)
4、through(設定管道陣列)
5、then(執行管道)
6、shouldSkipMiddleware
7、dispatchToRouter(獲取路由排程器回撥)

protected function sendRequestThroughRouter($request)
    {
        $this->app->instance('request', $request);//註冊請求例項到request

        Facade::clearResolvedInstance('request');//清除已解析的門面例項

        $this->bootstrap();//執行載入程式

        return (new Pipeline($this->app))
                    ->send($request)
                    ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                    ->then($this->dispatchToRouter());//中介軟體中的$next引數
    }

6. 為HTTP請求引導應用程式

1、hasBeenBootstrapped
2、bootstrapWith
3、bootstrappers

 public function bootstrap()
    {
        //判斷程式是否自舉
        if (! $this->app->hasBeenBootstrapped()) {
            $this->app->bootstrapWith($this->bootstrappers());//執行給定的引導類陣列
        }
    }

7. 返回路由排程器回撥(中介軟體中的$next引數)

protected function dispatchToRouter()
    {
        return function ($request) {
            $this->app->instance('request', $request);

            return $this->router->dispatch($request);
        };
    }

8. 終止核心

1、terminateMiddleware
2、 $this->app->terminate()

 public function terminate($request, $response)
    {
        $this->terminateMiddleware($request, $response);//終止中介軟體
        $this->app->terminate();//終止應用
    }

9. 終止中介軟體

1、shouldSkipMiddleware
2、gatherRouteMiddleware
3、parseMiddleware
4、make

    protected function terminateMiddleware($request, $response)
    {
        //獲取所有中介軟體
        $middlewares = $this->app->shouldSkipMiddleware() ? [] : array_merge(
            $this->gatherRouteMiddleware($request),//獲取當前請求的類的中介軟體
            $this->middleware//全域性公共中介軟體
        );

        foreach ($middlewares as $middleware) {
            if (! is_string($middleware)) {
                continue;
            }
            [$name] = $this->parseMiddleware($middleware);
            $instance = $this->app->make($name);//解析中介軟體例項
            if (method_exists($instance, 'terminate')) {
                $instance->terminate($request, $response);//執行中介軟體終止方法
            }
        }
    }

10. gatherRouteMiddleware

protected function gatherRouteMiddleware($request)
    {
        if ($route = $request->route()) {
            return $this->router->gatherRouteMiddleware($route);//使用解析的類名收集給定路由的中介軟體
        }
        return [];
    }

11. 解析中介軟體

 protected function parseMiddleware($middleware)
    {
        [$name, $parameters] = array_pad(explode(':', $middleware, 2), 2, []);
        if (is_string($parameters)) {
            $parameters = explode(',', $parameters);
        }
        return [$name, $parameters];
    }

12. hasMiddleware(是否存在全域性中介軟體)

public function hasMiddleware($middleware)
    {
        return in_array($middleware, $this->middleware);
    }

13. 插入新中介軟體到陣列頭部

public function prependMiddleware($middleware)
    {
        if (array_search($middleware, $this->middleware) === false) {
            array_unshift($this->middleware, $middleware);
        }
        return $this;
    }

14. 插入新中介軟體到陣列尾部

public function pushMiddleware($middleware)
    {
        if (array_search($middleware, $this->middleware) === false) {
            $this->middleware[] = $middleware;
        }

        return $this;
    }

15. bootstrappers(獲得應用載入程式)

protected function bootstrappers()
    {
        return $this->bootstrappers;
    }

16. 向異常處理程式報告異常

protected function reportException(Exception $e)
    {
        $this->app[ExceptionHandler::class]->report($e);
    }

17. 將異常輸出到響應

protected function renderException($request, Exception $e)
    {
        return $this->app[ExceptionHandler::class]->render($request, $e);
    }

18. getMiddlewareGroups

public function getMiddlewareGroups()
    {
        return $this->middlewareGroups;
    }

19. getApplication

 public function getApplication()
    {
        return $this->app;
    }
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章