Laravel’s entry file is index.php
$this, $Container, $this, $Container, $this
Registration of basic service providers (Event, log, routing),
Registration of core category names (such as DB, auth, config, Router, etc.)
$app->make(Illuminate\Contracts\Http\Kernel::class) resolves app \Http\ http.php from the container to the actual class
The HANDLE method processes the HTTP request
Is actually an HTTP request processed by the sendRequestThroughRouter in Handle
First, bind the request to the shared instance
Then execute the bootstarp method and run the $bootstrappers given an array of bootstrappers. This is the key. This includes loading configuration files, environment variables, providers for the service provider (in config/app.php), portal, exception handling, and bootappers
After that, it enters the pipeline mode and distributes the user requests after being processed and filtered by the middleware
When a request is distributed, it first looks for a route that matches a given request, and then executes the runRoute method, which actually handles the request with runRouteWithinStack in the runRoute method
Then, through the run method in runRouteWithinStack, the request is allocated to the actual controller and the response is obtained
4. Return the processing result
2, detailed source analysis 1, register automatic loader, automatic file loading
require __dir__.'/.. /vendor/autoload.php';Copy the code
Create an instance of the Application Container (which inherits from the Container class) and bind the core (Web, command line, exception) so that they can be resolved as needed
$app = require_once __DIR__.'/.. /bootstrap/app.php';Copy the code
App.php file is as follows:
<? [3] $app = new Illuminate\Foundation\Application($_ENV['APP_BASE_PATH']?? dirname(__DIR__) ); $app->singleton(Illuminate\Contracts\Http\ kernel ::class, app \Http\ kernel ::class); $app->singleton(Illuminate\Contracts\Console\ kernel ::class, app \Console\ kernel ::class); Kernel $app->singleton(Illuminate\Contracts\Debug\ExceptionHandler::class, app \Exceptions\Handler::class); Return $app;Copy the code
3. In the constructor that creates the Application instance (application.php), register the base binding into the container, register all the base service providers, and register the core class names in the container
Public function __construct($basePath = null) {$this->registerBaseBindings(); / / register all basic service provider [3.2] $this - > registerBaseServiceProviders (); / / registered in container core category name [3.3] $this - > registerCoreContainerAliases (); }Copy the code
3.1. Register the base binding with the container
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() )); # instance.instance (); To register as a shared instance, the Singleton method is to... Register as a share bindingCopy the code
3.2. Register all basic service providers (events, logs, routes)
protected function registerBaseServiceProviders()
{
$this->register(new EventServiceProvider($this));
$this->register(new LogServiceProvider($this));
$this->register(new RoutingServiceProvider($this));
}
Copy the code
3.3. Register the core category name in the container
This completes the auto-loading of classes, service provider registration, binding of core classes, and binding of basic registration
Index.php // 5.1$kernel = $app->make(Illuminate\Contracts\Http\ kernel ::class); $response = $kernel->handle($request = Illuminate\Http\ request ::capture());Copy the code
5.1 The make method parses the given value from the container
kernel =
kernel=app->make(Illuminate\Contracts\Http\Kernel::class);
$app = require_once __DIR__.’/.. /bootstrap/app.php’; The binding refers to the App/Http/Kernel::class class
5.2 HTTP requests are processed here
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
Copy the code
If you look at the $kernel class App\Http\ kernel.php, you can see that it only defines middleware content, and there is no handle method
Let’s go to its parent class, use Illuminate\Foundation\Http\Kernel as HttpKernel; If you look for the handle method, you can see that the handle method looks like this
Public function handle ($request) {try {/ / way deceive, don't pay any attention here $request - > enableHttpMethodParameterOverride (); [6] $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; }Copy the code
6. Handle HTTP requests (bind the request to a shared instance and process user requests using pipe mode)
Vendor/laravel/framework/SRC/Illuminate/Foundation/Http/Kernel. The handle method of PHP / / at the core of processing $response = Http requests $this->sendRequestThroughRouter($request);Copy the code
Enter the sendRequestThroughRouter method
Protected function sendRequestThroughRouter($this->app->instance('request', $this->app->instance) $request); / / will be asked to request from the appearance of the parsed examples to clear (as has been bound to the Shared instance, there is no need to waste resources) Facade: : clearResolvedInstance (" request "); $this->bootstrap(); [7, 8] // Enter the pipeline mode, through the middleware, Return ($this->app) ->send($request) -> Through ($this->app->shouldSkipMiddleware()? [] : $this->middleware) ->then($this->dispatchToRouter()); }Copy the code
7. In the bootstrap method, run the given bootstrap class array $bootstrappers, load the configuration file, environment variables, service provider, front, exception handling, bootstrap provider, A very important step position in vendor/laravel/framework/SRC/Illuminate/Foundation/Http/Kernel. The PHP
/** * Bootstrap the application for HTTP requests. * * @return void */ public function bootstrap() { if (! $this->app->hasBeenBootstrapped()) { $this->app->bootstrapWith($this->bootstrappers()); }} /** * Run the given array of bootstrappers ** @param string[] $bootstrappers * @return void */ 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]); } } /** * Get the bootstrap classes for the application. * * @return array */ protected function bootstrappers() { return $this->bootstrappers; } /** * Application bootloader class ** @var array */ protected $bootstrappers = [// load environment variables \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, / / loaded config configuration file [key], Illuminate, Foundation, the Bootstrap \ LoadConfiguration: : class, // Load exception handling \Illuminate\Foundation\Bootstrap\HandleExceptions::class, // Load the facade register \Illuminate\Foundation\Bootstrap\RegisterFacades::class, / / load in the config/app. In PHP will defined in an array of services, Illuminate, Foundation, 8 key 】 【 the Bootstrap \ RegisterProviders: : class, // Illuminate/Foundation/Bootstrap/BootProviders::class,];Copy the code
Load the service defined in the providers array in config/app.php
Illuminate\Auth\AuthServiceProvider::class, Illuminate\Broadcasting\BroadcastServiceProvider::class, Illuminate\Bus\BusServiceProvider::class, Illuminate\Cache\CacheServiceProvider::class, Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class, Illuminate\Cookie\CookieServiceProvider::class, Illuminate\Database\DatabaseServiceProvider::class, Illuminate\Encryption\EncryptionServiceProvider::class, Illuminate\Filesystem\FilesystemServiceProvider::class, Illuminate\Foundation\Providers\FoundationServiceProvider::class, Illuminate\Hashing\HashServiceProvider::class, Illuminate\Mail\MailServiceProvider::class, Illuminate\Notifications\NotificationServiceProvider::class, Illuminate\Pagination\PaginationServiceProvider::class, Illuminate\Pipeline\PipelineServiceProvider::class, Illuminate\Queue\QueueServiceProvider::class, Illuminate\Redis\RedisServiceProvider::class, Illuminate\Auth\Passwords\PasswordResetServiceProvider::class, Illuminate\Session\SessionServiceProvider::class, Illuminate\Translation\TranslationServiceProvider::class, Illuminate\Validation\ValidationServiceProvider::class, Illuminate\View\ViewServiceProvider::class, App\Providers\AppServiceProvider::class, App\Providers\AuthServiceProvider::class, App\Providers\EventServiceProvider::class, App \ will \ RouteServiceProvider: : class, / * * * yourself added service provider * / \ App \ will \ HelperServiceProvider: : class,Copy the code
As you can see, the common Redis, session, queue, auth, database, Route and other services are loaded here
9. Use pipeline mode to process user requests, which are processed by middleware first
Return (new Pipeline($this->app)) ->send($this->app) $this->app->shouldSkipMiddleware()? [] : $this->middleware) ->then($this->dispatchToRouter()); } app/Http/ kernel.php /** * Global Http middleware for your application ** 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, ];Copy the code
10. After being processed by the middleware, the request is distributed (including finding the matching route).
/** * 10.1 Send a given Request via middleware/router ** @param \Illuminate\Http\Request $Request * @return \Illuminate\Http\Response */ protected function sendRequestThroughRouter($request) { ... return (new Pipeline($this->app)) ... $this->dispatchToRouter(); } /** * 10.2 routing dispatcher callback ** @return \Closure */ protected function dispatchToRouter() {return function ($request) { $this->app->instance('request', $request); Return $this->router->dispatch($request); }; } /** * 10.3 Send the Request to the application ** @param \Illuminate\Http\Request $Request * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse */ public function dispatch(Request $request) { $this->currentRequest = $request; return $this->dispatchToRoute($request); } /** * 10.4 Assign the Request to the route and return the response [focus on runRoute method] ** @param \Illuminate\Http\Request $Request * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse */ public function dispatchToRoute(Request $request) { // return $this->runRoute($request, $this->findRoute($request)); } /** * 10.5 Find a Route that matches a given Request ** @param \Illuminate\Http\Request $Request * @return \Illuminate\Routing\Route */ protected function findRoute($request) { $this->current = $route = $this->routes->match($request); $this->container->instance(Route::class, $route); return $route; } /** * 10.6 Find the first Route that matches a given Request ** @param \Illuminate\Http\Request $Request * @return \Illuminate\Routing\Route ** @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function match(Request $request) { // $this->get($request->getMethod()); $routes = $this->get($request->getMethod()); $route = $this->matchAgainstRoutes($routes, $request); if (! is_null($route)) { return $route->bind($request); } $others = $this->checkForAlternateVerbs($request); if (count($others) > 0) { return $this->getRouteForMethods($request, $others); } throw new NotFoundHttpException; }Copy the code
At this point, you have found a route that matches the request, and then you will run the runRoute method in 10.4
/** * 10.4 Assign the Request to the route and return the response ** @param \Illuminate\Http\Request $Request * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse */ public function dispatchToRoute(Request $request) { return $this->runRoute($request, $this->findRoute($request)); } /** * 10.7 return the response to the given Route ** @param \Illuminate\Http\Request $Request * @param \Illuminate\Routing\Route $Route * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse */ 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) ); } /** * Run the given route within a Stack "onion" instance. ** @param \Illuminate\Routing\ route $route * @param \Illuminate\Http\Request $request * @return mixed */ 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() ); }); }Copy the code
As you can see, one of the methods in 10.7 is the prepareResponse, which creates an instance of the response from a given value, and the runRouteWithinStack method runs the route on the stack. That is, HTTP requests and responses are done here.