从了解PHP不久就想着用扩展的方式来实现PHP的程序框架,后来了解鸟哥已经实现了yaf简单的C实现PHP的MVC框架,故将其源代码研究了好几遍。yaf的优势是简单,高效,高性能,框架长驻内存,程序配置内存化,其实主要是运行速度比大部分PHP的框架都快。
1.在内核扩展中加载PHP用户空间类文件
文件:yaf_loader.c
函数:int yaf_loader_import( char path, int len int use_path TSRMLS_DC)
行号:333
2.自动加载器
原理:利用spl_autoload_register完成自动加载类
文件:yaf_application.c
函数:PHP_METHOD yaf_application __construct
行号:390
文件:yaf_loader.c
函数:yaf_loader_t * yaf_loader_instance(yaf_loader_t *this_ptr, char *library_path, char *global_path TSRMLS_DC)
行号:321
函数:int yaf_loader_register(yaf_loader_t *loader TSRMLS_DC)
行号:73
函数:PHP_METHOD(yaf_loader, autoload)
行号:695
2.格式化字符串输出到字符串指针
char *directory =NULL;
spprintf(&directory, 0, "%d/%s/%s", 45, "xy", "ab");
则:directory为45/xy/ab
3.smart_str结构体
文件:yaf_loader.c
函数:int yaf_internal_autoload (char file_name uint name_len char directory TSRMLS_DC)
行号:398
4.zend_file_handle结构体
文件:yaf_loader.c
函数:int yaf_loader_import (char path int len int use_path TSRMLS_DC)
行号:334
5.zend_compile_file
文件:yaf_loader.c
函数:int yaf_loader_import (char path int len int use_path TSRMLS_DC)
行号:348
6.plugin与route都需要在PHP用户空间手动添加,如:
在bootstrap文件中添加plugin
$user_plugin = new UserPlugin();
$dispatcher->registerPlugin($user_plugin);
在bootstrap文件中添加route
// 获取应用配置信息
$config = YafApplication::app()->getConfig();
// 注册配置
YafRegistry::set("config", $config);
// 通过派遣器获取路由器实例
$router = $dispatcher->getRouter();
// 通过配置文件添加路由器协议
$router->addConfig(YafRegistry::get('config')->routes);
7.Yaf_Controller_Abstract的init方法
继承Yaf_Controller_Abstract的控制器如果定义了init方法,那在控制器初始化时将调用init方法
文件:yaf_controller.c
函数:int yaf_controller_construct(zend_class_entry *ce, yaf_controller_t *self, yaf_request_t *request, yaf_response_t *response, yaf_view_t *view, zval *args TSRMLS_DC)
行号:230
8.与一般的框架不同, 在Yaf中, 可以定义动作的参数, 这些参数的值来自对Request的路由结果中的同名参数值,但是查看Yaf源码发现只有Yaf_route_static才实现了上述的动作参数
9.Yaf_Controller_Abstract::forward只是登记下要forward的目的地, 并不会立即跳转. 而是会等到当前的Action执行完成以后, 才会进行新的一轮dispatch
10.Dispatcher会修改路由结果的module,controller,action。如请求的url中没有指定模块,修正为默认模块;如将module,controller的首字母大小,action转化为全小写。
文件:yaf_dispatcher.c
函数:static inline void yaf_dispatcher_fix_default(yaf_dispatcher_t *dispatcher, yaf_request_t *request TSRMLS_DC)
行号:233
11.有些时候为了拆分比较大的Controller 使得代码更加清晰和易于管理 Yaf 支持将具体的动作分开定义。
12.yaf异常模式
当Application Configuration中设置application.dispatcher.throwException=1,yaf就会将PHP的错误触发改为异常抛出,当Application Configuration中设置application.dispatcher.catchException=1,那么yaf检测到有未捕获的异常时,yaf就会把运行权限交给当前模块的ErrorController中的errorAction。
源码中是通过检测EG(exception)PHP全局struct _zend_executor_globals结构体的exceptions成员状态来判断业务代码是否发现了异常,注意是业务代码,即从分发器Dispatcher开始分发,即YafApplication->run()调用yaf_dispatcher_dispatch()时,在每个分发的环节到最终执行Action检测代码是否发现了异常,因为每个分发环节完成之后都会调用宏YAF_EXCEPTION_HANDLE。