laravel5.5源码阅读草稿——入口

laravel的启动需要通过路由、中间件、控制器、模型、视图最后出现在浏览器。而路由、中间件、模型,这些功能都有自己的类,比如Route::any()、DB::table()、$this->middleware()等等,这些功能都是由一个叫IOC(服务容器)的对象来调配的。

它就像框架里的一个管家,我们需要某些功能的时候不需要去自己new、去考虑运行这A对象还需要把哪些对象传入A对象里才能运行了。laravel的index入口文件只管制造一个ioc实例,然后把request对象传入其中。

ioc容器中有一个叫provider的概念,大多数功能都有一个provider,它的作用就是把一个功能需要用到的类,这些类的路径及所需要的一些东西记录起来,在ioc实例化的时候调用其中一些基础服务。ioc在实例化的时候,会把一些基础的provider调用起来,这些基础provider又调用了自身的初始化函数,来实现了一些自动化功能。

在public/index.php文件内,laravel首先加载了autoload方法,似乎是通过composer的方式实现的;

随后引入bootstrap/app.php文件,文件内实例化了application类,并通过该应用实例注册了Http、Kernel、Handler的共享绑定。

再看application类,继承自Container类,并继承了ApplicationContract接口(另一个application类,应该是实现了部分系统方法),与http核心接口(这里通过symfony的请求与响应类来实现接口)

插一张不知道从哪盗来的Application的继承关系图

在laravel把系统基础核心初始化完毕后,便通过application 的 make 方法,传入了http核心的类名来获取别名(在container类的aliases属性中,存储了众多类名与别名的键值对,似乎是通过类名到别名,再到实例的方式来获取的,数组见下方)

 1 container->aliases
 2 =
 3 array:64 [▼
 4   "Illuminate\Foundation\Application" => "app"
 5   "Illuminate\Contracts\Container\Container" => "app"
 6   "Illuminate\Contracts\Foundation\Application" => "app"
 7   "Psr\Container\ContainerInterface" => "app"
 8   "Illuminate\Auth\AuthManager" => "auth"
 9   "Illuminate\Contracts\Auth\Factory" => "auth"
10   "Illuminate\Contracts\Auth\Guard" => "auth.driver"
11   "Illuminate\View\Compilers\BladeCompiler" => "blade.compiler"
12   "Illuminate\Cache\CacheManager" => "cache"
13   "Illuminate\Contracts\Cache\Factory" => "cache"
14   "Illuminate\Cache\Repository" => "cache.store"
15   "Illuminate\Contracts\Cache\Repository" => "cache.store"
16   "Illuminate\Config\Repository" => "config"
17   "Illuminate\Contracts\Config\Repository" => "config"
18   "Illuminate\Cookie\CookieJar" => "cookie"
19   "Illuminate\Contracts\Cookie\Factory" => "cookie"
20   "Illuminate\Contracts\Cookie\QueueingFactory" => "cookie"
21   "Illuminate\Encryption\Encrypter" => "encrypter"
22   "Illuminate\Contracts\Encryption\Encrypter" => "encrypter"
23   "Illuminate\Database\DatabaseManager" => "db"
24   "Illuminate\Database\Connection" => "db.connection"
25   "Illuminate\Database\ConnectionInterface" => "db.connection"
26   "Illuminate\Events\Dispatcher" => "events"
27   "Illuminate\Contracts\Events\Dispatcher" => "events"
28   "Illuminate\Filesystem\Filesystem" => "files"
29   "Illuminate\Filesystem\FilesystemManager" => "filesystem"
30   "Illuminate\Contracts\Filesystem\Factory" => "filesystem"
31   "Illuminate\Contracts\Filesystem\Filesystem" => "filesystem.disk"
32   "Illuminate\Contracts\Filesystem\Cloud" => "filesystem.cloud"
33   "Illuminate\Contracts\Hashing\Hasher" => "hash"
34   "Illuminate\Translation\Translator" => "translator"
35   "Illuminate\Contracts\Translation\Translator" => "translator"
36   "Illuminate\Log\Writer" => "log"
37   "Illuminate\Contracts\Logging\Log" => "log"
38   "Psr\Log\LoggerInterface" => "log"
39   "Illuminate\Mail\Mailer" => "mailer"
40   "Illuminate\Contracts\Mail\Mailer" => "mailer"
41   "Illuminate\Contracts\Mail\MailQueue" => "mailer"
42   "Illuminate\Auth\Passwords\PasswordBrokerManager" => "auth.password"
43   "Illuminate\Contracts\Auth\PasswordBrokerFactory" => "auth.password"
44   "Illuminate\Auth\Passwords\PasswordBroker" => "auth.password.broker"
45   "Illuminate\Contracts\Auth\PasswordBroker" => "auth.password.broker"
46   "Illuminate\Queue\QueueManager" => "queue"
47   "Illuminate\Contracts\Queue\Factory" => "queue"
48   "Illuminate\Contracts\Queue\Monitor" => "queue"
49   "Illuminate\Contracts\Queue\Queue" => "queue.connection"
50   "Illuminate\Queue\Failed\FailedJobProviderInterface" => "queue.failer"
51   "Illuminate\Routing\Redirector" => "redirect"
52   "Illuminate\Redis\RedisManager" => "redis"
53   "Illuminate\Contracts\Redis\Factory" => "redis"
54   "Illuminate\Http\Request" => "request"
55   "Symfony\Component\HttpFoundation\Request" => "request"
56   "Illuminate\Routing\Router" => "router"
57   "Illuminate\Contracts\Routing\Registrar" => "router"
58   "Illuminate\Contracts\Routing\BindingRegistrar" => "router"
59   "Illuminate\Session\SessionManager" => "session"
60   "Illuminate\Session\Store" => "session.store"
61   "Illuminate\Contracts\Session\Session" => "session.store"
62   "Illuminate\Routing\UrlGenerator" => "url"
63   "Illuminate\Contracts\Routing\UrlGenerator" => "url"
64   "Illuminate\Validation\Factory" => "validator"
65   "Illuminate\Contracts\Validation\Factory" => "validator"
66   "Illuminate\View\Factory" => "view"
67   "Illuminate\Contracts\View\Factory" => "view"
68 ]

http_kernel 的 bings属性为container容器所绑定

kernel obj的回调函数为容器自身所创建,在创建过程中,将一些回调函数进行绑定,并触发,但在index页面第一次初始化时,并没有回调函数被绑定触发,obj创建的过程还是不清楚。创建出的kernel对象里存储的是系统初始化所需的各种中间件与服务供应者的类名全称,见下方

index文件返回的kernel核心只是app/http/kernel的对象。而kernel核心在实例化时,依赖了application与route两个对象。并将自身的$middlewareGroups、routeMiddleware数组解析进了route对象里,在路由进行调用的时候就会把路由方法上绑定的中间件名在这里解析出实例来调用了,其中routeMiddleware为别名所用。

在创建出kernel实例后,通过其父类的handle方法加载了provider的基类,其加载了bootstrap引导函数。

依次执行$bootstrappers中每一个bootstrapper的bootstrap()函数

$bootstrappers = [
             ‘Illuminate\Foundation\Bootstrap\DetectEnvironment‘,
             ‘Illuminate\Foundation\Bootstrap\LoadConfiguration‘,
             ‘Illuminate\Foundation\Bootstrap\ConfigureLogging‘,
             ‘Illuminate\Foundation\Bootstrap\HandleExceptions‘,
             ‘Illuminate\Foundation\Bootstrap\RegisterFacades‘,
             ‘Illuminate\Foundation\Bootstrap\RegisterProviders‘,
             ‘Illuminate\Foundation\Bootstrap\BootProviders‘,
            ];

上面bootstrap中会分别执行每一个bootstrapper的bootstrap方法来引导启动应用程序的各个部分

1. DetectEnvironment 检查环境

2. LoadConfiguration 加载应用配置

3. ConfigureLogging 配置日至

4. HandleException 注册异常处理的Handler

5. RegisterFacades 注册Facades

6. RegisterProviders 注册Providers

7. BootProviders 启动Providers

启动应用程序的最后两步就是注册服务提供者和启动提供者,先来看注册服务提供器,服务提供器的注册由类\Illuminate\Foundation\Bootstrap\RegisterProviders::class负责,该类用于加载所有服务提供器的 register 函数,并保存延迟加载的服务的信息,以便实现延迟加载。

所有服务提供器都在配置文件 app.php 文件的 providers 数组中。类 ProviderRepository 负责所有的服务加载功能:

loadManifest()会加载服务提供器缓存文件services.php,如果框架是第一次启动时没有这个文件的,或者是缓存文件中的providers数组项与config/app.php里的providers数组项不一致都会编译生成services.php。

Illuminate\Foundation\Http\Kernel 的 dispatchToRouter 方法返回的闭包函数里包含了调用请求的代码。这段代码指向了Illuminate\Routing\router类

Illuminate\Routing\Route类的runCallable方法里对路由进行了调用

控制器和方法是从路由文件中获取到的(通过symfony的request对象获取到pathinfo),依然是通过字符串解析为类名和方法名,随后通过ioc容器实例化类为对象,再调用控制器基类的某个方法执行传入的方法名

Illuminate\Routing\ControllerDispatcher类的dispatch方法为真正执行的部分

插一张流程图

原文地址:https://www.cnblogs.com/wyycc/p/9601925.html

时间: 2024-11-13 09:52:13

laravel5.5源码阅读草稿——入口的相关文章

laravel5.5源码阅读草稿——application

构建方法传入整个项目根目录路径(public文件夹上一级)将其设为基础路径(存在本类basePath属性中). __construct > setBasePath > bindPathsInContainer 在容器中绑定路径 bindPathsInContainer > instance 在容器中注册已有实例 { $this->removeAbstractAlias($abstract);这个方法先删除了容器中的对应实例别名 (abstractAliases与aliases有区别

CI框架源码阅读笔记2 一切的入口 index.php

上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里这次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中,我们并不会逐行进行解释,而只解释核心的功能和实现. 1.       设置应用程序环境 define('ENVIRONMENT', 'development'); 这里的development可以是任何你喜欢的环境名称(比如dev,再如test),相对应的,你要在下面的switch case代码块中

CI框架源码阅读笔记3 全局函数Common.php

从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap引导文件都会最先引入全局函数,以便于之后的处理工作). 打开Common.php中,第一行代码就非常诡异: if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 上一篇(CI框架源码阅读笔记2 一切的入口 index

CI框架源码阅读笔记1 - 环境准备、基本术语和框架流程

最开始使用CI框架的时候,就打算写一个CI源码阅读的笔记系列,可惜虎头蛇尾,一直没有行动.最近项目少,总算是有了一些时间去写一些东西.于是准备将之前的一些笔记和经验记录下来,一方面权作备忘,另一方面时刻提醒自己:借鉴和学习才有出路,忘记过去意味着背叛! 基本术语说明 在本文开始之前,有必要对文中反复出现的术语做一个简单的说明,如果你对这一部分已经熟谙,完全可以略过.本文中反复出现和提及的术语包括: 前端控制器(Front Controller): 用于集中控制用户的所有请求的组件,将用户的请求发

ThinkPHP源码阅读3------行为扩展

ThinkPHP的核心采用的框架模式是CBD,也就是核心Core+行为Behavior+驱动Driver,核心也就是整个框架模式的核心,大部分都是一些基类,去规定规则,Behavior是行为,就是在指定的地方调用来完成一些特定的行为功能,而Driver驱动就类似cache缓存驱动,mysqldb 数据库驱动等,完成功能 行为在手册的13.1中说的很详细.我只去写一些实例.调用行为的方法. 调用方法是tags() /** * 处理标签扩展 * @param string $tag * 标签名称 *

seajs源码阅读

乘着周日有点时间,阅读一下玉伯大神的源码. seajs的源码写得真的很好,很是佩服,工整美观不愧是大神,造福百姓. 说起seajs不得不说,AMD和CMD的区别.  CMD 推崇依赖就近,AMD 推崇依赖前置. 事实上我对他们的区别没啥兴趣.关键是requirejs没明显的BUG,seajs明显没BUG. 两者最大区别请看这里:http://www.cnblogs.com/gyjWEB/p/4543945.html 好了,扯正题. 可以先看看别人写的源码解析:https://segmentfau

CI框架源码阅读笔记4 引导文件CodeIgniter.php

到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.com/usr/reg 经过引导文件,实际上会交给Application中的UsrController控制器的reg方法去处理. 这之中,CodeIgniter.php做了哪些工作?我们一步步来看. 1.    导入预定义常量.框架环境初始化 之前的一篇博客(CI框架源码阅读笔记2 一切的入

ThinkPHP源码阅读1-------访问流程

ThinkPHP访问流程在手册1.11系统流程里就有介绍,我阅读的ThinkPHP的版本是3.1.3,大家可以看下手册,基本的流程也有,现在就是详细去介绍一下ThinkPHP的访问流程.(调试模式下的,在部署模式下,会把中间的URL解析,文件加载之类的,都封装到一个文件里) 1.入口文件(index.php) 入口文件最常见得就是index.php,而在这里可以定义项目名称,路径,缓存文件存放路径之类的.最后要加载Thinkphp/ThinkPHP.php 指向下一个文件的地方是require

【jbpm4.4源码阅读笔记】engine的解析与生成

jpbm4.4源码的包结构主要有七个,分为org.jbpm.api;org.jbpm.bpmn;org.jbpm.enterprise.internal;org.jbpm.internal.log;org.jbpm.jpdl.internal;pvm.internal; 简而言之,api为接口,比如service.dao等的接口,bpmn定义了jbpm模型,比如task.end等节点的属性和动作,pvm即工作流虚拟机,是jbpm的核心实现:jpdl则是java process define la