来源 | CSDN博客精选

头图 | 视觉中国

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

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

PHP 的生命周期

生命周期

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

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

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

  3. 执行该PHP脚本。

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

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

PHP 的运行模式

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

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

  2. 当使用Nginx或者别web服务器作为宿主处理一个到来的请求时,使用的是WEB模式。

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

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

  2. 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自动加载需要的类

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

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

  3. 处理请求,生成并发送响应(对应代码3,毫不夸张的说,你99%的代码都运行在这个小小的handle 方法里面)。

  4. 请求结束,进行回调(对应代码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隔离在外。

更多精彩推荐
☞中国开源激荡 20 年:IT 江湖,谁主沉浮?
☞每个创始人都需要了解的来自 Y Combinator 的 13 个见解
☞那个从深圳流水线去了纽约做程序员的女工,最近失业了
☞没想到!!Unicode 字符还能这样玩?
☞为什么说机器学习是预防欺诈的最佳工具?
☞区块链是工业4.0的领引者
点分享点点赞点在看

图解 Laravel 请求的完整生命周期相关推荐

  1. 一文读懂机器学习项目的完整生命周期

    https://www.toutiao.com/a6675315427456844291/ 机器学习这东西,在学术界产出颇多,但在工业界,却很少落地.究其原因,是理念落地不够彻底,很多从业者和相关上下 ...

  2. 一张图搞懂Spring bean的完整生命周期

    转载自 一张图搞懂Spring bean的完整生命周期 一张图搞懂Spring bean的生命周期,从Spring容器启动到容器销毁bean的全过程,包括下面一系列的流程,了解这些流程对我们想在其中任 ...

  3. PMP —— 项目完整生命周期

    文章目录 PMP -- 项目完整生命周期 前言 一张图项目管理(以前端角度看) 角色介绍 注意事项 详细流程 项目立项 编写需求和需求评审 会议的主要步骤 参会角色思考 汇报工期 编写技术方案 什么是 ...

  4. java类的完整生命周期详解

    目录 一.概述 二.过程一:Loading(加载)阶段 1.加载完成的操作 (1)加载的理解 (2)加载完成的操作 2.二进制流的获取方式 3.类模型与Class实例的位置 (1)类模型的位置 (2) ...

  5. jsp学习(1)jsp请求过程和生命周期

    一.服务器处理jsp请求的过程: 以下步骤表明了 Web 服务器是如何使用JSP来创建网页的: 1.浏览器发送一个 HTTP 请求给服务器. 2.Web 服务器识别出这是一个对 JSP 网页的请求,并 ...

  6. Activity启动另一个Activity并返回的完整生命周期

    Android的简单基本问题,这里记录一下 从一个Activity创建后启动另一个Activity并返回的完整log输出: 从log可以看出,当前Activity启动另一个Activity时,总是要等 ...

  7. 微信小程序 网络请求接口 及 生命周期

    前言:前期我们对微信小程序有些基本了解,像标签,样式,组件....等. 今天我们继前期进行继续的了解 一. 网络请求 HTTP(HyperText Transfer Protocol)是一套计算机通过 ...

  8. 二、Vue(发送AJAX请求、Vue生命周期、计算属性、属性和方法、自定义指令、过渡(动画))

    一. 发送AJAX请求 1. 简介     vue本身不支持发送AJAX请求,需要使用vue-resource.axios等插件实现     axios是一个基于Promise的HTTP请求客户端,用 ...

  9. 从数据备份保护到完整生命周期管理平台,爱数全新发布 AnyBackup Family 8

    编辑 | 宋慧 出品 | CSDN 云计算 从2003年创业,开始做数据备份技术,爱数已经走过了近20年的时间.现在,数据的价值被越来越多的业界与用户看到,数据分析应用赛道近年一直持续火热.而现在的爱 ...

最新文章

  1. 最棒 Spring Boot 干货总结(超详细,建议收藏)
  2. python sys模块
  3. ddr5内存上市时间_DDR5内存明年才能上市,SK Hynix已预研DDR6:12Gbps
  4. Redis系列五、redis的五种数据结构和相关指令之Set
  5. Spark SQL 简介
  6. 中消协:要选择优质电子显示产品 OLED屏整体上略胜一筹
  7. Java基础学习总结(55)——java8新特性:stream
  8. 海龟交易法则10_通用积木
  9. c语言:猴子吃桃问题
  10. 疯狂Java讲义(读书笔记)(第六章--Java基础类库)
  11. 怎样用ipad使用python_如何用iPad运行Python代码?
  12. 题解【[FJOI2018]所罗门王的宝藏】
  13. Windows中redis设置密码
  14. oracle数据块的大小设置,Oracle数据块的大小
  15. Exoplayer简介
  16. python数据可视化——英雄联盟人物战力分析(条形图)
  17. php 变量 打字费劲,电脑自己打字停不下来
  18. Jmeter-----保存到响应文件
  19. 怎么将pdf转换excel转换器
  20. objectArx --- ADS篇

热门文章

  1. 基于SpringBoot从零构建博客网站 - 整合ehcache和开发注册登录功能
  2. 操作系统-Windows操作系统的线程调度了解这些
  3. LintCode 13. Implement strStr()
  4. hdu 6203 ping ping ping(贪心+树状数组+dfs序)
  5. 阅读下面程序,请回答如下问题:
  6. Jetson TK1 一:调整屏幕分辨率
  7. 《那些年啊,那些事——一个程序员的奋斗史》——54
  8. Reflector.exe + ilDasm.exe + ilasm.exe 破解DundasWebChart(VS2005) 5.5 成功
  9. 查看MySQL以及SQL Server 实际存储类型
  10. [论文阅读] Active Class Incremental Learning for Imbalanced Datasets