laravel的模块化是如何实现的
laravel的模块化是如何实现的
在laravel提供的官方文档上,有一个这样的名词 服务提供者,文档中介绍了它在laravel框架中的角色,以及如何使用它,但却没有讲明服务提供者的本质--它是为了解决什么问题而存在的? 不解决这一点,对于它的理解,则只会停留在表面.服务提供者是laravel实现模块化设计的手法.
为什么要进行模块化设计这里就不说的,可以参考下这些:模块化设计 , 模块化的意义何在?
为了实现模块化,必然要将一段程序组合起来,完成特定的事,从而形成模块.在laravel中, 一个模块都表现为一个Service.应用程序主体与组件(模块)之间必然要通过某种方式连接起来,才能使组件被主体所调用.在laravel中一个Service会被它的 Service Prorider 注入到ioc中,这样组件就与主体联系了起来, 具体的表现形式则是组件被主体所用,主体使用组件完成组件所擅长的事. 源代码是最好的文档,接下来,我们就看看"文档"是怎么说的.
laravel的启动过程
我们从启动开始,详细地分析在整个应用程序的生命周期中,Service Provider到底是什么?通过阅读源码方式来了解Serivce Provider在laravel中到底做了什么.
laravle的启动过程做了很多事,这里就不一一叙述了,主要说明有关Sevice Provider的部分.laravel有两个入口分别处理不同的请求1:public/index.php(http) 2.php arisan(cli).虽然入口有两种但它们的启动过程却相差无几(具体可以再详细了解这两种方式).
基础启动
bootstrap/app.php则是它的主要启动文件, 在\Illuminate\Foundation\Application::__construct中就可以看到应用主体的启动做了什么:
- 绑定Appliation和Container
- 注册最基础的Service Provider
- 注册别名
- 注册该应用程序的路径
上面启动过程的代码较简单,代码不分析了.就说一说为什么要做这几步,以及这几步对lavarel有什么作用.
laravel中以ioc为基础来构建应用程序的,所以,把这个最基础的Applicatoin放入容器中,供需要时可以随时从容器中提取使用(container 与 Application的关系看看代码就清晰了).
一个应用的合理运行必然离不开一些最基本的功能点,就像人类一样,虽然最重要的是大脑,但同样也不能没有血管,心脏.所以在laravel中也同样存在一些不可或缺的service provider, 比如事件和路由器.\Illuminate\Events\EventServiceProvider则把构建观察者的类注入到了ioc中,同时,在laravel源代码中大量使用了观察者模式来处理问题,\Illuminate\Routing\RoutingServiceProvider则把路由相关的服务注入到了主体中,因为一个http请求最不可或缺的当然是路由;
注册别名,则是为了调用ioc中的类时更方便,还有一点要注意是的,可以为一个类注册多个别名,为什么呢,其实这多个别名是存在关系的,它们大多是父类与子类的关系,就像Appliation和Container;
注册应用的路径则把一样常用的,跟应用有关的路径放到ioc中方便取用.启动的第一步到这就结束了.
http应用请求的启动
紧接着,又注册了三个类到ioc中,分别是http处理核心类,cli处理核心类,和异常处理.在这里注册了两种不同请亲的处理类,所以两个请求入口所做的事情都差不多了.接下来以http请求为例来,继续看下去.public/index.php:50则初始化了\App\Http\Kernel::__construct,也就初始化了中间件.接着public/index.php:52则调用了\Illuminate\Foundation\Http\Kernel::handle来处理请求,进一步看下去,也就是\Illuminate\Foundation\Http\Kernel::bootstrap中通过Application::bootstrapWith完成http请求环境的初始化,具体则是:
- 标记Application为已经引导启动状态
- 依次启动
\Illuminate\Foundation\Http\Kernel::$bootstrappers中的项目
1.Illuminate\Foundation\Bootstrap\DetectEnvironment:设置应用程序的环境
2.Illuminate\Foundation\Bootstrap\LoadConfiguration:载入应用程序的配置文件
3.Illuminate\Foundation\Bootstrap\ConfigureLogging:绑定日志处理类
4.Illuminate\Foundation\Bootstrap\HandleExceptions:异常处理
5.Illuminate\Foundation\Bootstrap\RegisterFacades:Facade模式的应用
6.Illuminate\Foundation\Bootstrap\RegisterProviders:注册Service Provider
7.Illuminate\Foundation\Bootstrap\BootProviders:标记启动完成 , 执行Srvice Provider的register方法,完成注入
然后,在vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:129就进入到了路由器,进而进入对应Controller进行处理,最后完成处理,请求结束.这一部分就不说了.
cli请求的启动
这一部分略,步骤与http类似
从它的请求生命周期可以看出以下几点
1:Service Provider在启动阶段就已经与注入了IOC
2:分为了两种,一种是由系统控制,而另一种则是可由用户控制.第一种是构成应用程序的基础,不能缺少;第二种则将控制权交给用户,由用户掌控应用的运行,比如加载第三方composer包,或自定义的Service等等.
此时,模块化已经初现雏形.在Controller中,可以调用或组合不同的Service, 来完成特定的逻辑,因为它已经在IOC中了;我们可以控制不同的Service或增或减,自定义这个应用程序的功能,成为新的系统.接下来,再看看Service Provider做了什么,使模块化在laravel中更完善.
注册Service Provider
在注册基础的Service Provider中,不难发现,完成注册过程的是\Illuminate\Foundation\Application::register,这个方法比较简单,一是执行了ServierProceder::register方法,通过这个接口将Service注册动IOC中;二是在系统已经启动的情况下,执行ServierProceder::boot方法,作用在这里讲的很清楚.
在注册用户自定义(config/app.php:124)时,\Illuminate\Foundation\Application::registerConfiguredProviders则完成了注册过程,其处理核心\Illuminate\Foundation\ProviderRepository::load主要做了以下几步
1:解析所有的Service Provider, 通过它的defer属性来决定是否延迟加载
2:将解析的结果,也就是一个Service Provider的数组,缓存为文件,下次直接载入解析后的缓存文件
3:只加载defer属性不为ture的Service Provider, 并注册
4:将延迟加载的放支容器中(APP::$deferredServices),在需要的时候再加载
从注册过程可以看出,我们可以定义Service Provider加载的时间,并不仅仅在启动这过程中加载,而是在需要的时候再加载.一种是通过\Illuminate\Foundation\Application::make;还有一种方式延迟加载则是在when方法中通过事件注册到某项事件上去,这一点则要好好看看\Illuminate\Foundation\ProviderRepository类了.
理清它的注册过程后,我们再仔细看看Service Provider的抽象类,它作为基类,提供了Servicer Provider能做的所有事情.了解它能更好的理解Service Provider.这个类并不复杂,唯一一个不是很清晰的只有commands方法:它将命令注册到了\Illuminate\Console\Events\ArtisanStarting事件中,为什么这样做? 在cli时,启动时,会有该事件的执行,从而通过Service Provider把命令注入到了IOC中,这样执行命令就行云流水了.
到这里,用Service Provider来实现模块化的功能得到了强化,既可以延迟加载,还可以注册命令.接下来,通过一些例子,看看它具体做了什么.
Service Provider的使用
Service Provider有很多,我们随便挑两个来看看
QueueServiceProvider
\Illuminate\Queue\QueueServiceProvider并非系统控制级别,看源代码,可以发现,里面有很多注册方法,注册了很多有关队列的类到IOC中,同时也注册了很多命令.在provides方法中,它返回的就是一个所有在这个Service Provider出现的的各个类,它是做什么的?其实我们可以发现,这个Service Provider是延迟加载的,所以这个Service所提供的各种服务并不会出现在服务中,上面我们说过,在需要的时候再加载.这一功能就是由provides中的返回值来决定的,当调用IOC中,那些延迟加载服务中出现的那些类时,再加载这些延迟的服务,从而可以获得延迟服务所提供的服务.
EventServiceProvider
\Illuminate\Events\EventServiceProvider是应用程序的核心,它又做了什么呢?
它也是向IOC中注册了事件处理的类,同时为这个类设置了队列解析的类.
HashServiceProvider
\Illuminate\Hashing\HashServiceProvider也向IOC注册一hash处理的类,并且是延迟加载的.
小结
查看Service Provicer的使用后,我们可以发现,它们都做了同们的事,就是把相应的服务注入到ICO中,以供使用,从而构成完成的系统.所以,现在我们就可以明白Service Provider是lararel完成模块化设计的方法,只不过融入了一些laravel自己的特点.
laravel的模块化是如何实现的的更多相关文章
- 详解如何在Laravel中增加自定义全局函数
http://www.php.cn/php-weizijiaocheng-383928.html 如何在Laravel中增加自定义全局函数?在我们的应用里经常会有一些全局都可能会用的函数,我们应该怎么 ...
- 基于 Laravel 5 构建的、支持模块化和多语言的 CMS —— AsgardCMS
1.简介 AsgardCMS 是基于 Laravel 5 构建的.支持模块化和多语言的CMS. 官网:https://asgardcms.com/ Github:https://github.com/ ...
- laravel学习:模块化caffeinated
# Modules Extract and modularize your code for maintainability. Essentially creates "mini-larav ...
- 用Laravel+Grunt+Bower管理你的应用
来源:http://yansu.org/2014/03/10/grunt-bower-and-laravel.html 为什么这么选择? 如今开源盛行,从后端的各个类库,到如今前端的jQuery插件, ...
- laravel 框架 开源的cms推荐
laravel 框架写的开源的cms系统 TypiCMS系统 多语言和模块化的CMS Laravel 5.2框架 下载地址:https://github.com/TypiCMS/Base Bootst ...
- 为什么Laravel是最成功的PHP框架?
Laravel 是一个有着美好前景的年轻框架,它的社区充满着活力,相关的文档和教程完整而清晰,并为快速.安全地开发现代应用程序提供了必要的功能.在近几年对PHP 框架流行度的统计中,Laravel始终 ...
- laravel框架详解
一.基础篇 1.概念 Laravel是一个有着美好前景的年轻框架,它的社区充满着活力,同时提供了完整而清晰的文档,而且为快速.安全地开发现代应用提供了必要的功能.2011年,Taylor Otwell ...
- Laravel View Composer - 当 include 一个模板时,自动获取其所需的变量
网站中,许多页面的侧边栏是相同的.例如: 分类列表页,与文章详情页的侧边栏都包含 最新文章 最新评论 统计计数 这些相同的侧边栏数据也是动态的,并不是固定的. 在每个 controller 里都写一遍 ...
- laravel项目thinksns+安装pc前端页面
前面我们说了laravel项目ThinkSNS+安装,现在要安装给用户看的页面,方便他们进行一些操作,比如发表文字/提问之类,这个已经模块化了,用composer就可以完成.命令行代码如下(之前是co ...
随机推荐
- struts1:(Struts重构)构建一个简单的基于MVC模式的JavaWeb
在构建一个简单的基于MVC模式的JavaWeb 中,我们使用了JSP+Servlet+JavaBean构建了一个基于MVC模式的简单登录系统,但在其小结中已经指出,这种模式下的Controller 和 ...
- html基础之 input:type
Input表示Form表单中的一种输入对象,其又随Type类型的不同而分文本输入框,密码输入框,单选/复选框,提交/重置按钮等,下面一一介绍.1,type=text输入类型是text,这是我们见的最多 ...
- zoj 1200 Mining
这道题被划到了动态规划里面去了,结果就是一道模拟题,懒了一点,直接用stl的优先队列,重载了一下运算符,写的时候保证只能一个在采,因为如果需要的采的次数比可以生产的次数少,那么生产的次数等于需要采的次 ...
- 初始AngularJS
<!-- AngularJS 通过 ng-directives 扩展了 HTML. ng-app 指令定义一个 AngularJS 应用程序. ng-model 指令把元素值(比如输入域的值)绑 ...
- CS0016: 未能写入输出文件*****目录名称无效
一大早,杀毒软件弹出删除隐私记录.清理空间一堆堆的提醒,一般我都是无视它,今天顺便点了下清理,然后出问题. 昨晚下班提交的代码,程序运行好好地,今早清理完系统,竟然就出问题了, 具体如下 CS0016 ...
- windows 文件watch nodejs
本篇博客,主要是记录下最近一直纠结的gulp.watch方法,在工作中我们肯定都遇到过,新添加的文件没办法自动触发watch,下面我们就来看有什么办法处理 1.首先我们肯定是先百度一下 百度推荐的是g ...
- Azure上Linux虚拟机Mac地址的持久化
有些用户在使用Azure Linux 虚拟机安装软件时,有些软件的license会和当前系统的mac地址绑定,那么在Azure VM重启,reszie(改变尺寸大小),停止然后再启动的时候,虚拟机的M ...
- android activity启动的时候隐藏软键盘
1.概述 android如果界面有EditText之类的跳软键盘的控件 在跳转到该界面是默认会跳出软键盘的. 更何况有些需求要直接需要获取焦点 <requestFocus /> 如果是E ...
- Delphi 常用API 函数(好多都没见过)
AdjustWindowRect 给定一种窗口样式,计算获得目标客户区矩形所需的窗口大小AnyPopup 判断屏幕上是否存在任何弹出式窗口ArrangeIconicWindows 排列一个父窗口的最小 ...
- (Inno setup打包)检测系统是否已安装程序,若已安装则弹出卸载提示的代码
原文 http://bbs.itiankong.com/thread-30983-1-5.html 有6天没研究pascal代码了,昨天晚上突然来了灵感,终于解决了苦思冥想好几天没能解决的问题, 因此 ...