Maison  >  Article  >  cadre php  >  Analyse détaillée du noyau HTTP dans Laravel

Analyse détaillée du noyau HTTP dans Laravel

不言
不言avant
2018-11-12 14:06:384115parcourir

Cet article vous apporte une analyse détaillée du noyau HTTP dans Laravel. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il vous sera utile.

Http Kernel

Http Kernel est utilisé dans Laravel pour connecter les composants principaux du framework afin d'effectuer des requêtes réseau. En termes simples, démarrez simplement le framework via public/index.php. Tous utiliseront le noyau Http, et d'autres qui sont traités via la commande artisan, les tâches planifiées et le cadre de démarrage de la file d'attente utiliseront le noyau de la console. Aujourd'hui, nous allons d'abord comprendre ce que fait le noyau Http.

Liaison du noyau

Étant donné que le noyau Http est utilisé dans Laravel pour connecter diverses parties du framework afin de traiter les requêtes réseau, examinons comment le noyau est chargé dans l'instance d'application dans Laravel. Dans public/index.php, nous verrons que l'application sera d'abord initialisée via le fichier d'échafaudage bootstrap/app.php :

Ce qui suit est le code de bootstrap/app.php, qui contient deux parties principales pour créer une instance d'application et lier le noyau au conteneur de service APP

<?php
// 第一部分: 创建应用实例
$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.&#39;/../&#39;)
);

// 第二部分: 完成内核绑定
$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
);

return $app;

Le noyau HTTP hérite de la classe IlluminateFoundationHttpKernel, qui définit un tableau lié au middleware dans le noyau HTTP. Le middleware fournit un mécanisme pratique pour filtrer les requêtes HTTP. entrant dans l’application et traitant les réponses HTTP sortant de l’application.

<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
    /**
     * The application&#39;s global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        \Illuminate\Foundation\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,
    ];
    /**
     * The application&#39;s route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        &#39;web&#39; => [
            \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 inpidually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    ];
}

Dans sa classe parent "IlluminateFoundationHttpKernel", un tableau d'amorçage avec le nom d'attribut "bootstrappers" est défini :

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,
];

Le groupe d'amorçage inclut l'achèvement de la détection et de la configuration de l'environnement le chargement, la gestion des exceptions, l'enregistrement des façades, l'enregistrement du fournisseur de services et le démarrage des services sont les six procédures d'amorçage.

Noyau d'analyse d'application

Après avoir lié le noyau Http au conteneur de service de l'application pendant la phase d'initialisation de l'application, nous pouvons voir l'utilisation du conteneur de service dans public/index.php La méthode make analyse sur l'instance du noyau HTTP :

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

Lors de l'instanciation du noyau, le middleware défini dans le noyau HTTP est enregistré sur le routeur. Après enregistrement, il peut être appelé avant de traiter réellement la requête HTTP appliquée. sur la route implémente l'objectif de filtrer les requêtes :

namespace Illuminate\Foundation\Http;
...
class Kernel implements KernelContract
{
    /**
     * Create a new HTTP kernel instance.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @param  \Illuminate\Routing\Router  $router
     * @return void
     */
    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);
        }
    }
}

namespace Illuminate/Routing;
class Router implements RegistrarContract, BindingRegistrar
{
    /**
     * Register a group of middleware.
     *
     * @param  string  $name
     * @param  array  $middleware
     * @return $this
     */
    public function middlewareGroup($name, array $middleware)
    {
        $this->middlewareGroups[$name] = $middleware;

        return $this;
    }
    
    /**
     * Register a short-hand name for a middleware.
     *
     * @param  string  $name
     * @param  string  $class
     * @return $this
     */
    public function aliasMiddleware($name, $class)
    {
        $this->middleware[$name] = $class;

        return $this;
    }
}

Traitement des requêtes HTTP

Après avoir terminé la création de l'instance principale HTTP via la résolution de service, vous pouvez utiliser l'instance principale HTTP pour traiter Requêtes HTTP.

//public/index.php
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

Avant de traiter la requête, une instance de requête Laravel Request sera créée sur la base des informations de la requête HTTP entrant dans l'application via la méthode capture() de la requête IlluminateHttpRequest. le cycle de vie restant de l'application. L'instance de requête est l'abstraction de cette requête HTTP

Après avoir abstrait la requête HTTP dans une instance de requête Laravel Request, l'instance de requête sera transmise dans la méthode handle du noyau HTTP. , et le traitement de la demande est terminé par la méthode handle de. La méthode

namespace Illuminate\Foundation\Http;

class Kernel implements KernelContract
{
    /**
     * Handle an incoming HTTP request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    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;
    }
}

handle reçoit un objet de requête et génère finalement un objet de réponse. En fait, nous connaissons déjà très bien la méthode handle lorsque nous expliquons de nombreux modules, nous l'utilisons comme point de départ et approfondissons progressivement le module pour expliquer la logique au sein du module. Parmi elles, la méthode sendRequestThroughRouter a été mentionnée dans. à la fois les fournisseurs de services et le middleware. Le programme de démarrage défini dans le noyau sera chargé pour démarrer l'application, puis l'objet Pipeline sera utilisé pour transmettre l'objet de requête HTTP et passer par le middleware HTTP et le middleware de routage définis dans le framework pour terminer le middleware HTTP. filtrage de la requête et enfin transmettre la requête au gestionnaire (une méthode de contrôleur ou une fermeture dans une route) avec la réponse correspondante renvoyée par le gestionnaire.

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());
}
    
/*引导启动Laravel应用程序
1. DetectEnvironment  检查环境
2. LoadConfiguration  加载应用配置
3. ConfigureLogging   配置日至
4. HandleException    注册异常处理的Handler
5. RegisterFacades    注册Facades 
6. RegisterProviders  注册Providers 
7. BootProviders      启动Providers
*/
public function bootstrap()
{
    if (! $this->app->hasBeenBootstrapped()) {
    /**依次执行$bootstrappers中每一个bootstrapper的bootstrap()函数
        $bootstrappers = [
             'Illuminate\Foundation\Bootstrap\DetectEnvironment',
             'Illuminate\Foundation\Bootstrap\LoadConfiguration',
             'Illuminate\Foundation\Bootstrap\ConfigureLogging',
             'Illuminate\Foundation\Bootstrap\HandleExceptions',
             'Illuminate\Foundation\Bootstrap\RegisterFacades',
             'Illuminate\Foundation\Bootstrap\RegisterProviders',
             'Illuminate\Foundation\Bootstrap\BootProviders',
            ];*/
            $this->app->bootstrapWith($this->bootstrappers());
    }
}

Envoyer la réponse

Après avoir parcouru les étapes ci-dessus, nous obtenons enfin que la réponse soit renvoyée, et l'étape suivante consiste à envoyer la réponse.

//public/index.php
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

// 发送响应
$response->send();

l'envoi d'une réponse est complété par la méthode IlluminateHttpResponse de la classe parent qui est définie dans la classe parent send(). SymfonyComponentHttpFoundationResponse

public function send()
{
    $this->sendHeaders();// 发送响应头部信息
    $this->sendContent();// 发送报文主题

    if (function_exists('fastcgi_finish_request')) {
        fastcgi_finish_request();
    } elseif (!\in_array(PHP_SAPI, array('cli', 'phpdbg'), true)) {
        static::closeOutputBuffers(0, true);
    }
    return $this;
}
Pour une analyse détaillée de l'objet Response, veuillez vous référer à notre chapitre précédent expliquant l'objet Response Laravel.

Terminer l'application

Une fois la réponse envoyée, le noyau HTTP appellera le

middleware pour effectuer un traitement ultérieur. Par exemple, le middleware « session » intégré de Laravel écrit les données de session dans le stockage une fois la réponse envoyée au navigateur. terminable

// public/index.php
// 终止程序
$kernel->terminate($request, $response);
//Illuminate\Foundation\Http\Kernel
public function terminate($request, $response)
{
    $this->terminateMiddleware($request, $response);
    $this->app->terminate();
}

// 终止中间件
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;
        }
        list($name, $parameters) = $this->parseMiddleware($middleware);
        $instance = $this->app->make($name);
        if (method_exists($instance, 'terminate')) {
            $instance->terminate($request, $response);
        }
    }
}
La méthode

du noyau HTTP appellera la méthode terminate du middleware teminable Une fois l'appel terminé, tout le cycle de vie de l'application, depuis la requête HTTP jusqu'à la réponse de retour, se termine. . terminate

Résumé

Le noyau HTTP présenté dans cette section joue principalement un rôle de série. Il est conçu pour initialiser les applications, guider les applications, résumer les requêtes HTTP dans des objets Request et transmettre les objets Request par le milieu. Le gestionnaire d'arrivée de fichiers génère une réponse et la réponse est envoyée au client.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer