先上一张官方运行流程图,然后来一步步分这个流程。
第一步,启动应用
yaf项目的入口在哪里?
一般是项目根目录下的index.php,是借助于rewrite规则定位到这里,也可以改写。
<?php
define('APP_PATH', dirname(__FILE__));
$app = new Yaf_Application(APP_PATH . "/conf/xxxxx.ini");
$app->bootstrap()->run();
实例化一个携带配置(指定一个配置文件路径)的Yaf_Application对象,调用它的bootstrap()方法指示Yaf_Application去寻找Bootstrap(默认在app.directory/Bootstrap.php,Yaf_Bootstrap_Abstract提供了一个可以定制Yaf_Application的最早的时机, 它相当于一段引导, 入口程序. 它本身没有定义任何方法.但任何继承自Yaf_Bootstrap的类中的以_init开头的方法, 都会在Yaf_Application::bootstrap时刻被调用. 调用的顺序和这些方法在类中的定义顺序相同. Yaf保证这种调用顺序.),然后调用run()方法运行这个Yaf_Application,开始接受并处理请求(这个方法只能调用一次,多次调用并不会有特殊效果),接着所有在Bootstrap类中定义的以_init开头的方法会被执行, 通过_initPlugin 加载 plugins->XXX.php, 插件类重写了两个路由hook(routerStartup、routerShutdown)。
第二步,浏览器访问url,路由解析url
当路由监听到浏览器访问,就会根据访问的uri构造出一个携带Module,Controller,Action信息的request,然后去访问具体模块下控制器的方法。
默认情况下,我们的路由器是Yaf_Router, 而默认使用的路由协议是Yaf_Route_Static。
Yaf_Route_Static分析请求中的request_uri, 在去除掉base_uri以后, 获取到真正的负载路由信息的request_uri片段, 具体的策略是, 根据”/”对request_uri分段。
那么可能有两种情况:
当uri有3段时(/module/controller/action),yaf会认为第一段是模块名,第二段是控制器名,第三段是动作名。
当uri有2段时(/controller/action),yaf会认为是去找默认模块index,第一段被认为是控制器名,第二段是动作名。
注意:默认Module是index,它的控制器是固定放在”{项目路径}/controllers” 目录下的,而其他自定义的Module是固定放在”{项目路径}/modules” 目录下的。另外,上面路由构造request找控制器的规则,也说明了mvc 的url结构访问的原理。
第三步,分发请求,调用控制器方法
路由构造出request后便关闭,接着框架会调用分发器的几个hook方法(dispatchLoopStartup,preDispatch,postDispatch),那么一般在postDispatch根据路由构造出来的request,去调用具体的控制器方法。
触发顺序 | 名称 | 触发时机 | 说明 |
---|---|---|---|
1 | routerStartup | 路由之前 | 触发最早的一个事件 |
2 | routerShutdown | 路由结束之后 | |
3 | routerStartup | 路由之前 | |
4 | preDispatch | 分发之前 | 如果勤求处理过程中发送了forward,则该事件可能触发多次 |
5 | postDispatch | 分发之后 | 动作执行结束,视图渲染完成,也可能触发多次 |
6 | dispatchLoopShutdown | 分发循环结束 | 所有业务逻辑已经完成,响应还未发送 |