头图 | 视觉中国

世间万物皆有生命周期,当我们利用任何工具时都须要理解它的事情事理,那么用起来就会得心应手,运用开拓也是如此。
理解了它的事理,那么利用起来就会游刃有余。

Laravel是一套简洁的PHP Web开拓框架(PHP Web Framework),本日,我们就来理解 一下Laravel 的生命周期。
在此之前,我们先回顾一下PHP 的生命周期。

php变量初始化图解 Laravel 要求的完全性命周期 GraphQL

PHP 的生命周期

生命周期

当我们要求一个php文件时,PHP 为了完成这次要求,会发生5个阶段的生命周期切换:

模块初始化(MINIT),即调用 php.ini 中指明的扩展的初始化函数进行初始化事情,如 mysql 扩展。

要求初始化(RINIT),即初始化为实行本次脚本所须要的变量名称和变量值内容的符号表,如 $_SESSION变量。

实行该PHP脚本。

要求处理完成(Request Shutdown),按顺序调用各个模块的 RSHUTDOWN 方法,对每个变量调用 unset函数,如 unset $_SESSION 变量。

关闭模块(Module Shutdown) , PHP调用每个扩展的 MSHUTDOWN 方法,这是各个模块末了一次开释内存的机会。
这意味着没有下一个要求了。

PHP 的运行模式

PHP两种运行模式是WEB模式、CLI模式。

当我们在终端敲入php这个命令的时候,利用的是CLI模式。

当利用Nginx或者别web做事器作为宿主处理一个到来的要求时,利用的是WEB模式。

WEB模式和CLI(命令行)模式很相似,差异是:

WEB模式为了应对并发,可能采取多线程,因此生命周期1和5有可能只实行一次,下次要求到来时重复2-4的生命周期,这样就节省了系统模块初始化所带来的开销。

CLI 模式会在每次脚本实行经历完全的5个周期,由于你脚本实行完不会有下一个要求。

可以看出PHP生命周期是很对称的。
说了这么多,便是为了定位Laravel运行在哪里,没错,Laravel仅仅运行再 第三个阶段:

理解这些,你就可以优化你的 Laravel 代码,可以更加深入的理解 Laravel 的singleton(单例)。
至少你知道了,每一次要求结束,PHP 的变量都会 unset,Laravel 的 singleton 只是在某一次要求过程中的singleton;你在 Laravel 中的静态变量也不能在多个要求之间共享,由于每一次要求结束都会 unset。
理解这些观点,是写高质量代码的第一步,也是最关键的一步。
因此记住,PHP是一种脚本措辞,所有的变量只会在这一次要求中生效,下次要求之时已被重置,而不像Java静态变量拥有全局浸染。

Laravel 的生命周期

Laravel 的生命周期从public\index.php开始,从public\index.php结束。

下面是 public\index.php的全部源码,更详细来说可以分为四步:

// 1require __DIR__.'/../bootstrap/autoload.php';// 2$app = require_once __DIR__.'/../bootstrap/app.php';$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);// 3$response = $kernel->handle( $request = Illuminate\Http\Request::capture);$response->send;// 4$kernel->terminate($request, $response);

以下是四步详细的阐明是:

composer自动加载须要的类

文件载入composer天生的自动加载设置,包括所有你 composer require的依赖。

天生容器Container,Application实例,并向容器注册核心组件(HttpKernel,ConsoleKernel ,ExceptionHandler)(对应代码2,容器很主要,后面详细讲解)。

处理要求,天生并发送相应(对应代码3,绝不夸年夜的说,你99%的代码都运行在这个小小的handle 方法里面)。

要求结束,进行回调(对应代码4,还记得可终止中间件吗?没错,便是在这里回调的)。

Laravel 的要求步骤,我们不妨在详细一点:

第一步:注册加载composer自动天生的class loader

便是加载初始化第三方依赖。

第二步:天生容器 Container

并向容器注册核心组件,是从 bootstrap/app.php 脚本获取 Laravel 运用实例。

这一步是重点,处理要求,并天生发送相应。

要求被发送到 HTTP 内核或 Console 内核,这取决于进入运用的要求类型。

取决于是通过浏览器要求还是通过掌握台要求。
这里我们紧张是通过浏览器要求。

HTTP 内核继续自 Illuminate\Foundation\Http\Kernel 类,该类定义了一个 bootstrappers 数组,这个数组中的类在要求被实行前运行,这些 bootstrappers 配置了缺点处理、日志、检测运用环境以及其它在要求被处理前须要实行的任务。

protected $bootstrappers = [ //注册系统环境配置 (.env) 'Illuminate\Foundation\Bootstrap\DetectEnvironment', //注册系统配置(config) 'Illuminate\Foundation\Bootstrap\LoadConfiguration', //注册日志配置 'Illuminate\Foundation\Bootstrap\ConfigureLogging', //注册非常处理 'Illuminate\Foundation\Bootstrap\HandleExceptions', //注册做事容器的门面,Facade 是个供应从容器访问工具的类。
'Illuminate\Foundation\Bootstrap\RegisterFacades', //注册做事供应者 'Illuminate\Foundation\Bootstrap\RegisterProviders', //注册做事供应者 `boot` 'Illuminate\Foundation\Bootstrap\BootProviders',];

把稳顺序:Facades 先于ServiceProviders,Facades也是重点,后面说,这里大略提一下,注册 Facades便是注册 config\app.php中的aliases

数组,你利用的很多类,如Auth,Cache,DB等等都是Facades;而ServiceProviders的register方法永久先于boot方法实行,以免产生boot方法依赖某个实例而该实例还未注册的征象。

HTTP 内核还定义了一系列所有要求在处理前须要经由的 HTTP 中间件,这些中间件处理 HTTP 会话的读写、判断运用是否处于掩护模式、验证 CSRF 令牌等等。

HTTP 内核的标志性方法 handle处理的逻辑相称大略:获取一个 Request,返回一个Response,把该内核想象作一个代表全体运用的大黑盒子,输入 HTTP 要求,返回 HTTP 相应。

第四步:将要求通报给路由

在Laravel根本的做事启动之后,就要把要求通报给路由了。
路由器将会分发要求到路由或掌握器,同时运行所有路由指定的中间件。

通报给路由是通过 Pipeline(管道)来通报的,但是Pipeline有一堵墙,在通报给路由之前所有要求都要经由,这堵墙定义在app\Http\Kernel.php中的$middleware数组中,没错便是中间件,默认只有一个CheckForMaintenanceMode中间件,用来检测你的网站是否暂时关闭。
这是一个全局中间件,所有要求都要经由,你也可以添加自己的全局中间件。

然后遍历所有注册的路由,找到最先符合的第一个路由,经由它的路由中间件,进入到掌握器或者闭包函数,实行你的详细逻辑代码。

以是,当要求到达你写的代码之前,Laravel已经做了大量事情,要求也经由了千难万险,那些不符合或者恶意的的要求已被Laravel隔离在外。