文档章节

Laravel源码入门-启动引导过程(四)app/Http/Kernel.php

zhmsong
 zhmsong
发布于 2017/05/13 21:29
字数 1463
阅读 407
收藏 0

== 回顾 ==

再来回顾一下 public/index.php ,代码如下(去掉详细注释部分)。

<?php // public/index.php

/**
 * Laravel - A PHP Framework For Web Artisans
 *
 * @package  Laravel
 * @author   Taylor Otwell <taylor@laravel.com>
 */

/*
|--------------------------------------------------------------------------
| Register The Auto Loader 注册类自动载入
|--------------------------------------------------------------------------
|
*/

require __DIR__.'/../bootstrap/autoload.php';

/*
|--------------------------------------------------------------------------
| Turn On The Lights 开灯点亮(创建$app实例)
|--------------------------------------------------------------------------
|
*/

$app = require_once __DIR__.'/../bootstrap/app.php';

/*
|--------------------------------------------------------------------------
| Run The Application 让应用跑起来
|--------------------------------------------------------------------------
|
*/

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

// 博文注释
// $kernel = $app->make(App\Http\Kernel::class);
// dump($kernel);

$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

$response->send();

$kernel->terminate($request, $response);

前文详细分析了 bootstrap/autoload.php 和 bootstrap/app.php,现在来看 $kernel 部分,这里第一行语句令人费解,如下:

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

不理解的地方在于 $kernel 来自于 make() 解析方法,就是说从一个类的名称中解析出来,而这个类是来自于协议中Http(面向Web,而不是Console)的Kernel,测试发现,实际上解析了 App\Http\Kernel。百思,应该是 bootstrap/app.php 中单例绑定的结果, 绑定语句如下:

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

这个 singleton() 将 协议中的Kernel 绑定到 App\Http\Kernel,也就出现了上面 make() 协议的Kernel也就是解析了App\Http\Kernel。这样做显然有个好处是,不管我们绑定哪个 Kernel,都可以实现 make() 到。

== 深入 App\Http\Kernel ==

 看看位置先,然后进入源代码。

 

 

 

<?php

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 = [
        \Illuminate\Foundation\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' => \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,
    ];
}

从源代码看到,App\Http\Kernel 继承自,核心基础库的 Illuminate\Foundation\Http\Kernel(以别名HttpKernel 出现),核心库 Kernel 的代码如下:

<?php  // laravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php

namespace Illuminate\Foundation\Http;

// 此处省略 use ...

class Kernel implements KernelContract
{
    /**
     * The application implementation.
     *
     * @var \Illuminate\Contracts\Foundation\Application
     */
    protected $app;

    /**
     * The router instance.
     *
     * @var \Illuminate\Routing\Router
     */
    protected $router;

    /**
     * The bootstrap classes for the application.
     * 引导类,起引导作用的类
     * 这些类里面基本上都有一个 bootstrap(Application $app) 方法,
     * 从不同的角度 bootstrap 应用。为最终 boot() 最准备。
     * 注意:这些事做不完,不能接受请求,或许连$request都无法正确生成。
     *
     * @var array
     */
    protected $bootstrappers = [
        // 载入服务器环境变量(.env 文件?)
        \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
        // 载入配置信息(config 目录?)
        \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
        // 配置如何处理异常
        \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
        // 注册 Facades
        \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
        // 注册 Providers
        \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
        // 启动 Providers
        \Illuminate\Foundation\Bootstrap\BootProviders::class,
    ];

    /**
     * The application's middleware stack.
     *
     * @var array
     */
    protected $middleware = [];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [];

    /**
     * The application's route middleware.
     *
     * @var array
     */
    protected $routeMiddleware = [];

Kernel 中还定义了重要的中间件列表,所有的请求 request 在被应用处理前,都必须经过这些中间件,筛过一遍后,才会被决定如何处理。这涉及到中间件(middleware)的作用。见 Kernel.php 中定义的中间件列表。

<?php // App\Http\Kernel.php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     * 应用全局范围的 HTTP中间件
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        // 检查是否出于维护模式
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        // 检查Post请求尺寸,太大报异常
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        // 除了密码外,都要trim — 去除字符串首尾处的空白字符(或者其他字符)
        \App\Http\Middleware\TrimStrings::class,
        // 转换空string('')为null。
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,

        // 以上这些类似于TP的公共函数 common,不过LA除了称其为中间件外,更进行了细分
    ];

    /**
     * The application's route middleware groups.
     * 路由中间件(数)组
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            // 加密Cookies:是否加密,例外处理等,继承自\Illuminate\Cookie的中间件
            \App\Http\Middleware\EncryptCookies::class,
            // Response头加入Cookies信息。
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            // 会话的中间件
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            // 视图的中间件
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            // 验证跨站请求伪造,我们的认识别停留在csrf层面,这些中间件就是处理请求的,
            // 一定要想办法处理伪造请求,La用中间件方式做了。
            \App\Http\Middleware\VerifyCsrfToken::class,
            // 路由替换绑定~~~???
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
 
            // 上面的类都有一个 handle($request, Closure $next),就是使用自己定义
            // 的规则对路由进行处理,然后安全了或者符合要求了 return $next($request)。
        ],

        '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' => \Illuminate\Auth\Middleware\Authenticate::class,
        // 基本验证:用 email 和 password 方式?
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        // 替换?TP 有 replace,一样?
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        // 用户权限,这个是比较具体的了,开发用到了
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    ];
}

上面的 $middleware[] 是面向全局的,特别是针对 HTTP 的,较为底层的?后面的 $middlewareGroups[] 和 $routeMiddleware[] 是比较具体的实施层面的。应该是可以根据开发需要继续添加。

总之,Kernel 做了两件事,第一个是定义 $bootstraps[],做好了 boot 系统的准备,第二个是定义 各种 middleware,这些都对 $request 进行加工、处理、甄选、判断,最终为可以形成正确的、有效的 $response 做准备,都完成后,进行了 index.php 中的 $kernel->handle($request),返回 $response。

== 总结 == 

$request ---> $kernel { service providers/middlewares/routers } ---> $response

Kernel 是就是个大黑箱,送入请求,输出响应,我们只管往里面添加服务、中间件、路由等等。                
 

© 著作权归作者所有

共有 人打赏支持
zhmsong
粉丝 41
博文 126
码字总数 65130
作品 0
海淀
程序员
Laravel VerifyCsrfToken 报错解决

别管我,我只是个背景 报错情况 form 表单进行 post 方式提交数据时,遇到如下的报错情况. post 数据提交报错 原因 Laravel 推荐在全局注册 VerifyCsrfToken 的 Middleware ,对所有 Post,P...

moTzxx
2017/08/29
0
0
laravel 5.2使用的那些坑

下载illuminate/html后 composer requireilluminate/html 用 {!! Form::close() !!} 报错 Call to undefined method IlluminateFoundationApplication::bindShared() 解决方法 将响应代码报错......

lilugirl
2016/03/21
641
0
laravel后台可修改配置自动加载

1、laravel实现的生产环境跟开发环境配置分离 通常我们会把配置文件所需要的参数放在/config下面的目录中,这个文件夹下面的所有文件都会自动加载,我们使用config(文件名+”.”+配置项)的方...

tree2013
2016/03/27
885
0
Laravel框架一:原理机制篇

http://www.cnblogs.com/XiongMaoMengNan/p/6644892.html Laravel作为在国内国外都颇为流行的PHP框架,风格优雅,其拥有自己的一些特点。 一. 请求周期   Laravel 采用了单一入口模式,应用...

hisense20112784
2017/08/11
0
0
makesurprise/laravel-routecache-middleware

Laravel 5 Page Cache Use Middleware Add page cache with route. The cache is best not to write in the program logic inside, to find a cache is very tired, I suggest that the cach......

makesurprise
2015/11/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

OSChina 周三乱弹 —— 公司女同事约我

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子:分享水木年华的单曲《蝴蝶花(2002年大提琴版)》 《蝴蝶花(2002年大提琴版)》- 水木年华 手机党少年们想听歌,请使劲儿戳(这里) ...

小小编辑
10分钟前
28
7
Linux环境搭建 | VMware下共享文件夹的实现

在进行程序开发的过程中,我们经常要在主机与虚拟机之间传递文件,比如说,源代码位于虚拟机,而在主机下阅读或修改源代码,这里就需要使用到 「共享文件」 这个机制了。本文介绍了两种共享文...

良许Linux
今天
5
0
JUC锁框架——AQS源码分析

JUC锁介绍 Java的并发框架JUC(java.util.concurrent)中锁是最重要的一个工具。因为锁,才能实现正确的并发访问。而AbstractQueuedSynchronizer(AQS)是一个用来构建锁和同步器的框架,使用A...

长头发-dawn
今天
3
0
docker中安装了RabbitMQ后无法访问其Web管理页面

在官网找了"$ docker run -d --hostname my-rabbit --name some-rabbit -p 8080:15672 rabbitmq:3-management"这条安装命令,在docker上安装了RabbitMQ,,结果输入http://localhost:8080并不......

钟然千落
今天
4
1
spring-cloud | 分布式session共享

写在前面的话 各位小伙伴,你们有福了,这一节不仅教大家怎么实现分布式session的问题,还用kotlin开发,喜欢kotlin的小伙伴是不是很开心! 以前在写Android的时候,就对客户端请求有一定的认...

冯文议
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部