Laravel源码入门-启动引导过程(四)app/Http/Kernel.php
2017-05-13 21:29
597 查看
== 回顾 ==
再来回顾一下 public/index.php ,代码如下(去掉详细注释部分)。
前文详细分析了 bootstrap/autoload.php 和 bootstrap/app.php,现在来看 $kernel 部分,这里第一行语句令人费解,如下:
不理解的地方在于 $kernel 来自于 make() 解析方法,就是说从一个类的名称中解析出来,而这个类是来自于协议中Http(面向Web,而不是Console)的Kernel,测试发现,实际上解析了 App\Http\Kernel。百思,应该是 bootstrap/app.php 中单例绑定的结果, 绑定语句如下:
这个 singleton() 将 协议中的Kernel 绑定到 App\Http\Kernel,也就出现了上面 make() 协议的Kernel也就是解析了App\Http\Kernel。这样做显然有个好处是,不管我们绑定哪个 Kernel,都可以实现 make() 到。
== 深入 App\Http\Kernel ==
看看位置先,然后进入源代码。
从源代码看到,App\Http\Kernel 继承自,核心基础库的 Illuminate\Foundation\Http\Kernel(以别名HttpKernel 出现),核心库 Kernel 的代码如下:
Kernel 中还定义了重要的中间件列表,所有的请求 request 在被应用处理前,都必须经过这些中间件,筛过一遍后,才会被决定如何处理。这涉及到中间件(middleware)的作用。见 Kernel.php 中定义的中间件列表。
上面的 $middleware[] 是面向全局的,特别是针对 HTTP 的,较为底层的?后面的 $middlewareGroups[] 和 $routeMiddleware[] 是比较具体的实施层面的。应该是可以根据开发需要继续添加。
总之,Kernel 做了两件事,第一个是定义 $bootstraps[],做好了 boot 系统的准备,第二个是定义 各种 middleware,这些都对 $request 进行加工、处理、甄选、判断,最终为可以形成正确的、有效的 $response 做准备,都完成后,进行了 index.php 中的 $kernel->handle($request),返回 $response。
== 总结 ==
$request ---> $kernel { service providers/middlewares/routers } ---> $response
Kernel 是就是个大黑箱,送入请求,输出响应,我们只管往里面添加服务、中间件、路由等等。
再来回顾一下 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 是就是个大黑箱,送入请求,输出响应,我们只管往里面添加服务、中间件、路由等等。
相关文章推荐
- Laravel源码入门-启动引导过程(三)bootstrap/app.php
- Laravel源码入门-启动引导过程(一)public/index.php
- Laravel源码入门-启动引导过程(十二)Pipeline
- Laravel源码入门-启动引导过程(六)LoadEnvironmentVariables
- Laravel源码入门-启动引导过程(八)HandleExceptions
- Laravel源码入门-启动引导过程(十一)BootProviders
- Laravel源码入门-启动引导过程(七)LoadConfiguration
- Laravel源码入门-启动引导过程(十)RegisterProviders
- Laravel源码入门-启动引导过程(九)RegisterFacades
- Laravel源码入门-启动引导过程(五)$kernel->handle($request)
- Laravel源码入门-启动引导过程(二)bootstrap/autoload.php
- XSBase255 -linux 启动过程描述 引用自http://www.linuxeden.com/forum/blog/index.php?op=ViewArticle&articleId=230&blogId=102509
- php: CGI faseCGI PHP-FPM | laravel启动过程 | php依赖注入
- IOS开发入门----UIApplication和AppDelegate以及IOS程序启动的过程(2017/8/8)
- Android 源码二:Android系统启动和App启动过程
- kvm安装与启动过程说明-Kernel源码编译方式
- Laravel5.5源码详解 -- 数据库的启动与连接过程
- 从源码角度解析android APP启动过程中各类及其方法的调用
- PHP源码分析之启动过程
- kernel 启动过程之四,start_kernel中的rest_init函数到init进程