Laravel框架的运行过程
Laravel框架的入口文件public/index.php
<?php/*** Laravel - A PHP Framework For Web Artisans** @package Laravel* @author Taylor Otwell <taylor@laravel.com>*/define('LARAVEL_START', microtime(true));/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader for
| our application. We just need to utilize it! We'll simply require it
| into the script here so that we don't have to worry about manual
| loading any of our classes later on. It feels great to relax.
|
*/require __DIR__.'/../vendor/autoload.php';/*
|--------------------------------------------------------------------------
| Turn On The Lights
|--------------------------------------------------------------------------
|
| We need to illuminate PHP development, so let us turn on the lights.
| This bootstraps the framework and gets it ready for use, then it
| will load up this application so that we can run it and send
| the responses back to the browser and delight our users.
|
*/$app = require_once __DIR__.'/../bootstrap/app.php';/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request
| through the kernel, and send the associated response back to
| the client's browser allowing them to enjoy the creative
| and wonderful application we have prepared for them.
|
*/$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);$response = $kernel->handle($request = Illuminate\Http\Request::capture()
);$response->send();$kernel->terminate($request, $response);
根据作者的注释可以知道这几行代码的作用:
- 定义常量记录框架启动时间。
- 加载composer包管理器中的自动加载器到当前命名空间(根命名空间)。
- 获取一个Application类的实例$app,这个实例继承了Container类,并且作为一个服务容器承担连接各种服务的功能,我们可以从这个容器获取各种服务,如日志、数据库、缓存、事件等。
- 调用$app的make方法获取一个kernel类,用kernel类处理请求对象(Request类的实例,包含了请求信息),之后返回一个$response来发送响应,最后调用$kernel的terminate方法结束本次请求,这样,一个完整的http请求就完成了。
框架的启动过程在kernel调用handle方法时进行,那么启动框架到底做了什么事情?这就要深入了解下kernel类的handle方法了。
找到kernel类文件中的handle 方法:
/*** 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;}
这个方法接受一个\Illuminate\Http\Request请求类实例作为参数,然后返回一个\Illuminate\Http\Response响应类。正常请求会调用sendRequestThroughRouter方法,翻过过来就是:“将请求送往路由”,然后返回响应,如果产生异常则调用异常处理方法,将异常信息包装为响应类。接下来看下sendRequestThroughRouter方法:
/*** Send the given request through the middleware / router.** @param \Illuminate\Http\Request $request* @return \Illuminate\Http\Response*/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());}
这个方法并不长,只有四行代码:
- 调用服务容器的instance方法绑定一个request实例
- 调用Illuminate\Support\Facades\Facade类(门面类基类)的clearResolvedInstance静态方法清除resolvedInstance属性(已解析实例)中的’request’实体。
- 调用bootstrap方法启动框架。
- new一个管道类,依次调用send、through、then方法使请求通过中间件,最后分发到路由类处理。
看到这里,就知道框架的启动过程放在了bootstrap方法,继续看下这个方法:
/*** Bootstrap the application for HTTP requests.** @return void*/public function bootstrap(){if (! $this->app->hasBeenBootstrapped()) {$this->app->bootstrapWith($this->bootstrappers());}}
判断框架是否启动,未启动则调用服务容器的bootstrapWith方法,传入了kernel的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,];
继续看下服务容器的bootstrapWith方法:
/*** Run the given array of bootstrap classes.** @param string[] $bootstrappers* @return void*/public function bootstrapWith(array $bootstrappers){$this->hasBeenBootstrapped = true;foreach ($bootstrappers as $bootstrapper) {$this['events']->dispatch('bootstrapping: '.$bootstrapper, [$this]);$this->make($bootstrapper)->bootstrap($this);$this['events']->dispatch('bootstrapped: '.$bootstrapper, [$this]);}}
在这个方法中只有几行代码,将启动属性修改为已启动,然后遍历bootstrappers 数组,启动框架的过程就是一个加载基础类的过程:发布启动事件,调用make方法实例化基础类然后调用基础类的bootstrap方法,然后发布完成启动事件。bootstrappers 数组中的类都定义在laravel源码包 的Foundation目录的子目录Bootstrap中。这些类的功能:
- 加载环境变量
- 加载配置文件
- 加载异常处理类
- 注册门面类
- 注册服务提供类
- 启动服务类
以上就是laravel框架的启动全过程,我们在框架启动之后,还未处理请求之前调用一下框架的辅助函数dd()和app()来打印下服务容器对象:
protected function sendRequestThroughRouter($request){$this->app->instance('request', $request);Facade::clearResolvedInstance('request');$this->bootstrap();
dd(app());return (new Pipeline($this->app))->send($request)->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)->then($this->dispatchToRouter());}
打印结果:
Application {#2 ▼#basePath: "/vagrant/www/laravel5.8"#hasBeenBootstrapped: true#booted: true#bootingCallbacks: array:1 [▶]#bootedCallbacks: array:1 [▶]#terminatingCallbacks: []#serviceProviders: array:22 [▶]#loadedProviders: array:22 [▶]#deferredServices: array:102 [▶]#appPath: null#databasePath: null#storagePath: null#environmentPath: null#environmentFile: ".env"#namespace: null#resolved: array:20 [▶]#bindings: array:41 [▶]#methodBindings: []#instances: array:26 [▼"path" => "/vagrant/www/laravel5.8/app""path.base" => "/vagrant/www/laravel5.8""path.lang" => "/vagrant/www/laravel5.8/resources/lang""path.config" => "/vagrant/www/laravel5.8/config""path.public" => "/vagrant/www/laravel5.8/public""path.storage" => "/vagrant/www/laravel5.8/storage""path.database" => "/vagrant/www/laravel5.8/database""path.resources" => "/vagrant/www/laravel5.8/resources""path.bootstrap" => "/vagrant/www/laravel5.8/bootstrap""app" => Application {#2}"Illuminate\Container\Container" => Application {#2}"Illuminate\Foundation\PackageManifest" => PackageManifest {#5 ▶}"events" => Dispatcher {#27 ▶}"router" => Router {#26 ▶}"Illuminate\Contracts\Http\Kernel" => Kernel {#30 ▶}"request" => Request {#43 ▶}"config" => Repository {#34 ▶}"db.factory" => ConnectionFactory {#53 ▶}"db" => DatabaseManager {#37 ▶}"view.engine.resolver" => EngineResolver {#105 ▶}"files" => Filesystem {#111}"view" => Factory {#112 ▶}"translation.loader" => FileLoader {#119 ▶}"translator" => Translator {#120 ▶}"routes" => RouteCollection {#29 ▶}"url" => UrlGenerator {#128 ▶}]#aliases: array:66 [▶]#abstractAliases: array:36 [▶]#extenders: []#tags: []#buildStack: []#with: []+contextual: array:1 [▶]#reboundCallbacks: array:2 [▶]#globalResolvingCallbacks: []#globalAfterResolvingCallbacks: []#resolvingCallbacks: array:1 [▶]#afterResolvingCallbacks: array:1 [▶]
}
可以看到在处理请求之前,服务容器中的instances共享实例属性,就已经注册了十几个对象,而在处理请求的过程中又还要注册很多对象,这也就不难理解为什么laravel框架的并发性较差了。
Laravel框架的运行过程相关推荐
- php larval框架运行环境,Laravel框架的运行环境配置(一)
Laravel框架 学习参考: Laravel的特点; 单一入口:所有请求必须从单入口开始,主要是关于管理[统一的参数过滤] MVC的思想 ORM操作数据库 一个模型对应数据库里面的一张表,对象的属性 ...
- laravel框架实践1
一.Laravel简介 Laravel是一套简洁,优雅的PHPWeb开发框架 具有富于表达性且简洁的语法 Laravel是易于理解且强大的,它提供了强大的工具用以开发大型,健壮的应用. 具有验证.路由 ...
- Laravel框架的简介、安装以及启动。
一.Laravel简介 Laravel是一套简洁,优雅的PHP Web开发框架 具有富于表达性且简洁的语法 Laravel是易于理解且强大的,它提供了强大的工具用以开发大型,健壮的应用. 具有验证.路 ...
- 关于laravel框架中and 和orWhere 的多条件嵌套
最近的项目一直在使用laravel框架,在使用过程中突然发现自带的助手函数where()与orWhere()使用起来和自己预想中的不一样,特此记录学习防止以后忘记. 举个例子我们需要查找状态为1,名称 ...
- 【Laravel框架】简介
目录 导语 一.简介 二.开发环境配置与要求 三.PHP的注意事项 Laravel 简介 导语 Laravel是一套简洁,优雅的PHPWeb开发框架,具有富于表达性且简洁的语法 Laravel是易于理 ...
- php框架laravel原理,Laravel框架运行原理
写在前面: 使用任何框架,如果理解该框架原理,应用起来会更加得心应手. 一.生命周期 1. 入口文件: Laravel框架所有请求入口统一进入/public/index.php文件,请求通过Ngxin ...
- 关于laravel 框架运行数据库迁移文件的一个小坑以及常用php artisan命令
小白我因为最近开发的一系列项目都是用的laravel框架,所以为了方便有时候就会直接复制一份代码以此作为新项目的基础.可能因为"因为夜路走多了,所以掉坑里了">>> ...
- php larval框架运行环境,4种Windows系统下Laravel框架的开发环境安装及部署方法详解...
1.准备工作 1.1PHP集成环境 这里我们使用的是XAMPP,XAMPP是一个功能强大的建站集成软件包,采用一键安装的方式,包含PHP7.0.Mysql.Tomcat等.最新版下载地址:PHP 5. ...
- php runtimeexception,Laravel框架运行出错提示RuntimeException No application encryption...
关于Laravel,出错提示,RuntimeException,No,application,encryption,key,has,been,specified.,解决方法,Laravel框架运行出错 ...
- Laravel框架一:原理机制篇
转载自http://www.cnblogs.com/XiongMaoMengNan/p/6644892.html Laravel作为在国内国外都颇为流行的PHP框架,风格优雅,其拥有自己的一些特点. ...
最新文章
- visio二次开发___事件篇___事件分类
- webpack增量打包多页应用
- 《研磨设计模式》chap15 组合模式(2)改写示例+总结
- 手把手带你复现ICCV 2017经典论文—PyraNet
- 【ArcGIS遇上Python】ArcGIS Python按照指定字段批量筛选不同类型的图斑(以土地利用数据为例)
- P3889-[GDOI2014]吃【线段树】
- [react] react16的reconciliation和commit分别是什么?
- 2018 Machine Learning
- pat乙级相当于什么水平_英语四六级/专四/专八相当于美国人什么水平?
- PacMan开发-碰撞检测实现
- InnoDB存储引擎MVCC的工作原理
- 导师说,再招女生,他就是孙子
- 伺服驱动器--增益调整
- java编程基本基本框架_盘点Java编程中常用的框架
- 基于拦截器实现防表单重复提交
- 类似京东商城客户端应用iOS源码
- 数值分析matlab最小二乘法,数值分析 最小二乘 matlab
- 程序员去外包的后遗症是什么
- 奥维地图怎么标注文字_如何在奥维地图上准确地告诉别人“我在哪?”
- DTOJ 4745. 进制转换
热门文章
- 都2022了,我为什么还要写博客?
- mysql8 错误日志_MySQL 8 服务器日志
- 计算机网络总复习题(含答案)
- python代码控制机械臂_Dobot 机械臂
- 移动计算的未来:是什么在推动变革? | 幂集创新
- ant安装配置使用介绍及eclipse中使用
- Cisco VPP fib.h中文对照
- java 传智播客 毕向东_传智播客,毕向东Java详细基础教程下载
- 常用元器件使用方法4:一种Micro-SIM卡连接器的使用方法
- hash算法_Win10_64 默认应用的UserChoice Hash算法学习