larvel服務加載及運行流程


1.程序的初始化

1.1.我們先看入口文件index.php

larvel服務加載及運行流程

這是larvel的入口文件在public目錄下

<code>引入啦 require_once __DIR__.'/../bootstrap/app.php';
在這個文件裡實力化了Application類
$app = new Illuminate\\Foundation\\Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);/<code>

1.2在查看源碼的時候,我們應該看這個類的構造函數所以我們進到這個類中

<code>這是構造函數
public function __construct($basePath = null)
{

// 設置框架的地址
if ($basePath) {
$this->setBasePath($basePath);
}
// 註冊應用實例容器
$this->registerBaseBindings();

// 註冊應用服務提供者
$this->registerBaseServiceProviders();

// 註冊應用的實例對象別名 -> 容器別名
$this->registerCoreContainerAliases();
// dd($this->instances);
}

registerBaseBindings函數方法如下
protected function registerBaseBindings()
{
static::setInstance($this);

$this->instance('app', $this);

$this->instance(Container::class, $this);

$this->singleton(Mix::class);


$this->instance(PackageManifest::class, new PackageManifest(
new Filesystem, $this->basePath(), $this->getCachedPackagesPath()
));
}

registerBaseServiceProviders函數如下
protected function registerBaseServiceProviders()
{
//註冊時間服務
$this->register(new EventServiceProvider($this));
//測試日誌服務
$this->register(new LogServiceProvider($this));
// 這裡只是加載路由的實例對象
// 但不是註冊 自定義路由
$this->register(new RoutingServiceProvider($this));
}

/<code>

1.3,這時構造函數看完拉,接著看app.php這個文件

<code>這也是註冊服務,對於核心實例及契約綁定標示
註冊larvel啟動的核心類庫(請求,控制檯,異常等)
$app->singleton(
Illuminate\\Contracts\\Http\\Kernel::class,
App\\Http\\Kernel::class
);

$app->singleton(
Illuminate\\Contracts\\Console\\Kernel::class,
App\\Console\\Kernel::class
);

$app->singleton(
Illuminate\\Contracts\\Debug\\ExceptionHandler::class,
App\\Exceptions\\Handler::class
);/<code>

目前為止引入app.php文件已經看完拉


1.3.index.php 往下看

<code>//通過契約,從容器中實化App\\Http\\Kernel::class larvel處理處理http 核心
$kernel = $app->make(Illuminate\\Contracts\\Http\\Kernel::class); // App\\Http\\Kernel::class
在看這個類的構造函數但是發現沒有構造函數

namespace App\\Http;

use Illuminate\\Foundation\\Http\\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array
*/
protected $middleware = [
\\App\\Http\\Middleware\\TrustProxies::class,
\\App\\Http\\Middleware\\CheckForMaintenanceMode::class,
\\Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize::class,
\\App\\Http\\Middleware\\TrimStrings::class,
\\Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull::class,
];

/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
\\App\\Http\\Middleware\\EncryptCookies::class,
\\Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse::class,
\\Illuminate\\Session\\Middleware\\StartSession::class,
// \\Illuminate\\Session\\Middleware\\AuthenticateSession::class,

\\Illuminate\\View\\Middleware\\ShareErrorsFromSession::class,
\\App\\Http\\Middleware\\VerifyCsrfToken::class,
\\Illuminate\\Routing\\Middleware\\SubstituteBindings::class,
],

'api' => [
'throttle:60,1',
'bindings',
],
];

/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'auth' => \\App\\Http\\Middleware\\Authenticate::class,
'auth.basic' => \\Illuminate\\Auth\\Middleware\\AuthenticateWithBasicAuth::class,
'bindings' => \\Illuminate\\Routing\\Middleware\\SubstituteBindings::class,
'cache.headers' => \\Illuminate\\Http\\Middleware\\SetCacheHeaders::class,
'can' => \\Illuminate\\Auth\\Middleware\\Authorize::class,
'guest' => \\App\\Http\\Middleware\\RedirectIfAuthenticated::class,
'password.confirm' => \\Illuminate\\Auth\\Middleware\\RequirePassword::class,
'signed' => \\Illuminate\\Routing\\Middleware\\ValidateSignature::class,
'throttle' => \\Illuminate\\Routing\\Middleware\\ThrottleRequests::class,
'verified' => \\Illuminate\\Auth\\Middleware\\EnsureEmailIsVerified::class,
];

/**
* The priority-sorted list of middleware.
*
* This forces non-global middleware to always be in the given order.
*
* @var array
*/
protected $middlewarePriority = [
\\Illuminate\\Session\\Middleware\\StartSession::class,
\\Illuminate\\View\\Middleware\\ShareErrorsFromSession::class,
\\App\\Http\\Middleware\\Authenticate::class,
\\Illuminate\\Routing\\Middleware\\ThrottleRequests::class,
\\Illuminate\\Session\\Middleware\\AuthenticateSession::class,
\\Illuminate\\Routing\\Middleware\\SubstituteBindings::class,
\\Illuminate\\Auth\\Middleware\\Authorize::class,
];
}
?>

我們只能去父類裡面看Illuminate\\Foundation\\Http\\Kernel

/<code>

1.4在看index.php

<code>//dd($kernel);
// 執行用戶的請求
$response = $kernel->handle(
$request = Illuminate\\Http\\Request::capture()//返回
);
Illuminate\\Foundation\\Http\\Kernel類中的handle方法

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;
}



//1.共享請求實例對象
//2.調用$this->bootstrap();引導larvel加載額外的內容實例以及配置信息
//3.創建管道並執行對應的中間件

//4.進行路由分發
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());//dispatchToRouter 路由分發
}



public function bootstrap()
{

if (! $this->app->hasBeenBootstrapped()) {
// dd($this->bootstrappers());
//方法通告make創建實例並引導執行類中的bootstrap方法
$this->app->bootstrapWith($this->bootstrappers());
}
}

/<code>

2.請求分發

<code>dispatchToRouter()函數
//$this->router是那個類那,可以看構造函數,裡面實例化啦\\Illuminate\\Routing\\Router
protected function dispatchToRouter()
{
return function ($request) {
$this->app->instance('request', $request);
// $this->router => \\Illuminate\\Routing\\Router
return $this->router->dispatch($request);
};
}

所以我們該看\\Illuminate\\Routing\\Router 類中的dispatch方法

public function dispatch(Request $request)
{
$this->currentRequest = $request;

return $this->dispatchToRoute($request);
}

調用$this->dispatchToRoute($request);

public function dispatchToRoute(Request $request)
{
//findRoute 查找路由
//runRoute 運行路由
return $this->runRoute($request, $this->findRoute($request));
}

//查找路由
protected function findRoute($request)
{
// $this->routes => \\Illuminate\\Routing\\RouteCollection 在構造函數當中new
// dd($request);
//match 進行最終的校驗
//1.根據請求獲取路由
//2.進行路由的的檢測和校驗通過 在RouteCollection類中的matchAgainstRoutes()
$this->current = $route = $this->routes->match($request);

$this->container->instance(Route::class, $route);

return $route;
}


//運行路由
protected function runRoute(Request $request, Route $route)
{
$request->setRouteResolver(function () use ($route) {
return $route;
});

$this->events->dispatch(new Events\\RouteMatched($route, $request));

return $this->prepareResponse($request,
$this->runRouteWithinStack($route, $request)//看這裡
);

}

protected function runRouteWithinStack(Route $route, Request $request)
{
$shouldSkipMiddleware = $this->container->bound('middleware.disable') &&
$this->container->make('middleware.disable') === true;
// 獲取全局中間件
$middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddleware($route);
// dd($middleware);
return (new Pipeline($this->container))
->send($request)
->through($middleware)
->then(function ($request) use ($route) {
return $this->prepareResponse(
$request, $route->run() //看這裡會運行\\Illuminate\\Routing\\Route裡的run()
);
});
}




//運行\\Illuminate\\Routing\\Route裡的run()
public function run()
{
//dd($this->container);
$this->container = $this->container ?: new Container;
// dd($this->isControllerAction());
try {
//判斷是不是控制器如果是控制器就會調用runController()不是$this->runCallable();
if ($this->isControllerAction()) {
return $this->runController();
}

return $this->runCallable();
} catch (HttpResponseException $e) {
return $e->getResponse();
}
}/<code>

到這裡就大概看完了,細節還要各位往方法裡看哦


分享到:


相關文章: