搜索
首页php框架LaravelLaravel中HTTP内核的详细解析

Laravel中HTTP内核的详细解析

Nov 12, 2018 pm 02:06 PM
laravel

本篇文章给大家带来的内容是关于Laravel中HTTP内核的详细解析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

Http Kernel

Http Kernel是Laravel中用来串联框架的各个核心组件来网络请求的,简单的说只要是通过public/index.php来启动框架的都会用到Http Kernel,而另外的类似通过artisan命令、计划任务、队列启动框架进行处理的都会用到Console Kernel, 今天我们先梳理一下Http Kernel做的事情。

内核绑定

既然Http Kernel是Laravel中用来串联框架的各个部分处理网络请求的,我们来看一下内核是怎么加载到Laravel中应用实例中来的,在public/index.php中我们就会看见首先就会通过bootstrap/app.php这个脚手架文件来初始化应用程序:

下面是 bootstrap/app.php 的代码,包含两个主要部分创建应用实例和绑定内核至 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;

HTTP 内核继承自 IlluminateFoundationHttpKernel类,在 HTTP 内核中 内它定义了中间件相关数组, 中间件提供了一种方便的机制来过滤进入应用的 HTTP 请求和加工流出应用的HTTP响应。

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

在其父类 「IlluminateFoundationHttpKernel」 内部定义了属性名为 「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,
];

引导程序组中 包括完成环境检测、配置加载、异常处理、Facades 注册、服务提供者注册、启动服务这六个引导程序。

应用解析内核

在将应用初始化阶段将Http内核绑定至应用的服务容器后,紧接着在public/index.php中我们可以看到使用了服务容器的make方法将Http内核实例解析了出来:

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

在实例化内核时,将在 HTTP 内核中定义的中间件注册到了 路由器,注册完后就可以在实际处理 HTTP 请求前调用路由上应用的中间件实现过滤请求的目的:

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

处理HTTP请求

通过服务解析完成Http内核实例的创建后就可以用HTTP内核实例来处理HTTP请求了

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

在处理请求之前会先通过Illuminate\Http\Request的 capture() 方法以进入应用的HTTP请求的信息为基础创建出一个 Laravel Request请求实例,在后续应用剩余的生命周期中Request请求实例就是对本次HTTP请求的抽象

将HTTP请求抽象成Laravel Request请求实例后,请求实例会被传导进入到HTTP内核的handle方法内部,请求的处理就是由handle方法来完成的。

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 方法接收一个请求对象,并最终生成一个响应对象。其实handle方法我们已经很熟悉了在讲解很多模块的时候都是以它为出发点逐步深入到模块的内部去讲解模块内的逻辑的,其中sendRequestThroughRouter方法在服务提供者和中间件都提到过,它会加载在内核中定义的引导程序来引导启动应用然后会将使用Pipeline对象传输HTTP请求对象流经框架中定义的HTTP中间件们和路由中间件们来完成过滤请求最终将请求传递给处理程序(控制器方法或者路由中的闭包)由处理程序返回相应的响应。

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

发送响应

经过上面的几个阶段后我们最终拿到了要返回的响应,接下来就是发送响应了。

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

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

发送响应由 Illuminate\Http\Responsesend()方法完成父类其定义在父类Symfony\Component\HttpFoundation\Response中。

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

关于Response对象的详细分析可以参看我们之前讲解Laravel Response对象的章节。

终止应用程序

响应发送后,HTTP内核会调用terminable中间件做一些后续的处理工作。比如,Laravel 内置的「session」中间件会在响应发送到浏览器之后将会话数据写入存储器中。

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

Http内核的terminate方法会调用teminable中间件的terminate方法,调用完成后从HTTP请求进来到返回响应整个应用程序的生命周期就结束了。

总结

本节介绍的HTTP内核起到的主要是串联作用,其中设计到的初始化应用、引导应用、将HTTP请求抽象成Request对象、传递Request对象通过中间件到达处理程序生成响应以及响应发送给客户端。

以上是Laravel中HTTP内核的详细解析的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:segmentfault。如有侵权,请联系admin@php.cn删除
掌握Laravel软删除:最佳实践和高级技术掌握Laravel软删除:最佳实践和高级技术May 08, 2025 am 12:25 AM

laravelsoftdeletesallow“删除” withoutremovingRecordSssfromtheDatabase.toimplement:1)usethesoftdeletdeleterationyourmodel.2)usewithtrashed()toincludesoft-deletedrecordsinquordsinquordsinquordsinquordsinquordsinquordsinquordsinquordsinquordsinquordsinquor sinecustomscopemscopemscopeslikeonlikeOnlikeOnlikeOnlikeOnlikeNiqueniendselline)

Laravel软删除:恢复和永久删除记录Laravel软删除:恢复和永久删除记录May 08, 2025 am 12:24 AM

在Laravel中,恢复被软删除的记录使用restore()方法,永久删除使用forceDelete()方法。1)恢复单个记录使用withTrashed()->find()->restore(),多个记录使用onlyTrashed()->restore()。2)永久删除单个记录使用withTrashed()->find()->forceDelete(),多个记录使用onlyTrashed()->forceDelete()。

当前的Laravel版本:今天下载和升级!当前的Laravel版本:今天下载和升级!May 08, 2025 am 12:22 AM

你应该下载并升级到最新的Laravel版本,因为它提供了增强的EloquentORM功能和新的路由特性,这些更新可以提高应用程序的效率和安全性。要升级,请按照以下步骤:1.备份当前应用程序,2.更新composer.json文件至最新版本,3.运行更新命令。虽然可能会遇到一些常见问题,如废弃函数和包兼容性,但通过参考文档和社区支持,这些问题都可以解决。

Laravel:我什么时候应该更新到最后一个版本?Laravel:我什么时候应该更新到最后一个版本?May 08, 2025 am 12:18 AM

youshouldupdateTothelateStlaravelversionwhentheBeneFitsClearlyOutweighTheCosts.1)newfeaturesandimprovementCanenhanceCarenHanceYourApplication.2)SecurityUpdatesArecrucialifvulnerabilitysareaddresse.3)

Laravel软删除:如何防止永久数据丢失Laravel软删除:如何防止永久数据丢失May 08, 2025 am 12:04 AM

laravel'softdeletefeaturecanbeusedeffectife tosafeguarddatabyfollowingspecificstepsandBestPractices.1)启动fortdeletsesoftDeletDeletEstraitInyourModel.2)usewitheStraitInyourModel.2)usewithwithtrashed()

Laravel版本跟踪器:始终了解最新版本Laravel版本跟踪器:始终了解最新版本May 07, 2025 pm 06:25 PM

开发者可以通过以下方式高效跟踪Laravel的新版本并确保使用最新和最安全的代码库:1.使用代码片段检查最新版本并与当前版本比较,2.利用Composer和Laravel的更新机制进行依赖管理,3.实施自动化测试以处理版本冲突,4.通过社区互动获取新版本反馈,5.关注Laravel的公开路线图和GitHub动态以规划更新。

Laravel Last最早版本:安全更新Laravel Last最早版本:安全更新May 07, 2025 pm 05:25 PM

Laravel的最新版本(9.x)带来了重要的安全更新,主要包括:1)修补已知漏洞,如CSRF攻击;2)增强整体安全性,如CSRF保护和SQL注入防御。通过理解和正确应用这些更新,你可以确保你的Laravel应用始终处于最安全的状态。

Laravel迁移的最终指南:数据库结构管理Laravel迁移的最终指南:数据库结构管理May 07, 2025 pm 05:05 PM

LaravelMigrationsReverversionControlforDatabases,允许Chemamanageandandevolution.1)heelpmainteamsyncandCandConsistencyCrossenvironments.2)usethemtocreateTeTablesLikeTablesLikethe'users'sosers'sobles'usersorablewithnenselaryfields.3)ModifyExistingTableSingTableSingTableSingTablesbyDablesbyAddingDingfieldSlikeSlike'phon

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用