Phalcon框架启动流程(部分源码)分析

Phalcon框架启动流程(部分源码)分析

 

创建项目

A、通过命令行生成一个标准的Phalcon多模块应用

phalcon project demo modules(phalcon project store  (micro-微型, simple - 单应用, modules-多应用 )  - 默认是单应用文档结构)

B、通过手工的方式创建

入口文件为public/index.php,简化后一共7行,包含了整个Phalcon的启动流程,以下将按顺序说明

use Phalcon\Mvc\Application;

$config = include APP_PATH . "/apps/frontend/config/config.php";

require __DIR__ . '/../config/services.php';

$application = new Application($di);

require __DIR__ . '/../config/modules.php';

require __DIR__ . '/../config/routes.php';

echo $application->handle()->getContent();

 

DI注册阶段

Phalcon的所有组件服务都是通过DI(依赖注入)进行组织的,这也是目前大部分主流框架所使用的方法。通过DI,可以灵活的控制框架中的服务:哪些需要启用,哪些不启用,组件的内部细节等等,因此Phalcon是一个松耦合可替换的框架,完全可以通过DI替换MVC中任何一个组件。

require __DIR__ . '/../config/services.php';

这个文件中默认注册了Phalcon\Mvc\Router(路由)、Phalcon\Mvc\UrlUrl)、Phalcon\Mvc\Model\MetaData\Memory(ORM表结构)、Phalcon\Session\Adapter\FilesSession)三个最基本的组件。同时当MVC启动后,DI中默认注册的服务还有很多,可以通过DI得到所有当前已经注册的服务:

$services = $application->getDI()->getServices();

    foreach ($services as $key => $value) {

        var_dump($key);

        var_dump(get_class($application->getDI()->get($key)));

}

打印看到Phalcon还注册了以下服务:

Router:Phalcon\Mvc\Router 路由

Dispatcher:Phalcon\Mvc\Dispatcher 分发服务,把路由命中的结果分发到对应的controller

Url:Phalcon\Mvc\Url 

modelsManager:Phalcon\Mvc\Model\Manager Model管理器

modelsMetadata:Phalcon\Mvc\Model\MetaData\Memory ORM表结构

Response:Phalcon\Http\Response 响应

Cookies:Phalcon\Http\Response\Cookies Cookies管理

Request:Phalcon\Http\Request 请求

Filter:Phalcon\Filter 可对用户提交数据进行过滤

Escaper:Phalcon\Escaper 转义工具

Security:Phalcon\Security  密码Hash、防止CSRF等

Crypt:Phalcon\Crypt 加密算法

Annotations:Phalcon\Annotations\Adapter\Memory 注解分析

Flash:Phalcon\Flash\Direct 闪存,提示信息输出

flashSession:Phalcon\Flash\Session 提示信息通过session延迟输出

Tag:Phalcon\Tag  View的常用Helper

Session:Phalcon\Session\Adapter\Files session

每个服务都可以通过DI进行替换。接着来实例化一个标准的MVC应用,然后我们把定义好DI注册进去:

$application = new Phalcon\Mvc\Application();

$application->setDI($di);

 

模块注册阶段

DI一样,phalcon 可以通过引入一个独立的文件实现模块的注册:

require __DIR__ . '/../config/modules.php';

文件内容如下:

$application->registerModules(array(

    'frontend' => array(

        'className' => 'Phalconsmvc\Frontend\Module',

        'path' => __DIR__ . '/../apps/frontend/Module.php'

    )

));

可以看到phalcon的模块注册,其实是告诉框架MVC的模块引导文件Module.php文件所在位置及类名是什么。

 

MVC阶段

$application->handle()是整个框架MVC的核心,这个函数负责处理模块、控制器、分发等MVC的流程。具体的执行流程如下:

基础检查阶段:

首先检查依赖对象服务DI是否注册,如果没有注册DI则抛出异常

A dependency injection object is required to access internal services

 

事件启动:

从DI启动eventsManager,并通过eventsManager管理器触发application:boot事件。

 

路由处理阶段:

从DI服务获得router(路由)服务,把uri传入路由并调用handle()方法。

handle()方法负责根据uri配置把请求转换到对应的Module、Controller、Action等。这一阶段会检查是否命中模块,并通过router->getModuleName()获得模块名称。

如果模块存在,则进入模块启动阶段,如果模块不存在则直接进入路由分发阶段。可见路由的启动是先于模块的启动的。

 

模块启动:

在模块启动时会先调用application:beforeStartModule方法,根据modules.php的配置检查模块的正确性、名称、路径是否存在等,并把模块引导文件引进来。把模块内的action、service注册为自动加载。

moduleObject->registerAutoloaders(dependencyInjector);

moduleObject->registerServices(dependencyInjector);

registerAutoloaders()用于注册模块内的命名空间实现自动加载;registerServices ()用于注册模块内服务。

 

 

路由dispatcher分发阶段:

分发阶段由Phalcon\Mvc\Dispatcher(分发器)来完成,分发器跟进路由命中的结果调用相应的controller/action,最终获得action返回的结果。

在分发前会准备view,理论上MVC流程中view是最后一环节,但是分发过程中出现任何问题都需要显示出来,因此view层必须在这个环节提前启动。

分发需要dispatcher服务,可以从DI服务获得,dispatcher根据router传过来的参数设置模块名称、命名空间、控制器、动作、参数,分发启动开始前会调用view->start()启动缓存,分发过程中所有输出都会被暂存到缓冲区

分发时会先调用application:beforeHandleRequest方法检查dispatcher是否已经注册,然后调用dispatcher->dispatch()进行分发作业。

 

View渲染阶段

分发结束后通过Phalcon\Mvc\Dispatcher->getReturnedValue()取得分发过程返回的结果并进行处理。

由于action的逻辑在框架外,action的返回结构是无法预知的,因此这里跟进返回结构决定是否调用ResponseInterface接口进行区分处理。当action返回非returnedResponse对象的时候,view自己重新调度Render过程,会触发application:viewRender事件,通过dispatcher获得controllerName、actionName、params参数作为Phalcon\Mvc\View->render()的入口参数。

Render过程结束后,调用Phalcon\Mvc\View->finish()刷新缓冲区数据。

接下来从DI获取response服务,将Phalcon\Mvc\View->getContent()获得的内容置入response。

 

返回响应

通过前面的流程,最终会返回一个响应给前台。此时会触发application:beforeSendResponse,并调用

 

Phalcon\Http\Response->sendHeaders()

Phalcon\Http\Response->sendCookies()

http的头部信息先行发送。至此,Application->handle()对于请求的处理过程全部结束,对外返回一个Phalcon\Http\Response响应。

 

发送响应

HTTP头部发送后一般把响应的内容也发送出去:

echo $application->handle()->getContent();

这就是Phalcon Framework的完整MVC流程。

你可能感兴趣的:(PHP)