关于yaf的控制器命名,一个纠结的问题(续)
来源:互联网 发布:吉利易云制造数据平台 编辑:程序博客网 时间:2024/06/10 02:59
loader相关的步骤,已经补上!
前面写过一篇《关于yaf的控制器命名,一个纠结的问题》。没想到yaf群里面也有跟我遇到一样问题的人,分享下解决办法。
写完那篇博文后,我尝试了多种思路,又是SPL又是配置的,历经了不少坎坷,但还是顺利的达成了我想要的目标。还是那句老话,办法总比困难多。下面,我介绍一下我的这个方案,不过这个方案的基本原理是修改yaf的源码重新编译,不喜欢这个方案的同学可以忽略本文了。
What
我们要达成什么样的目标?
1、修改yaf控制器的命名规范,如ZF一样:“控制器类名 = 模块名_控制器名Controller”,文件命名不变。
2、为了兼容以前缺省模块中的代码,在缺省模块中,控制器命名规则使用yaf默认的规则,即:“控制器类名 = 控制器名Controller”。
How
how之前,我们有必要先弄清Why。
前面的文章里说过了,yaf之所以不支持根据模块名来区分控制器,是因为在yaf 的自动加载过程中对这些特定命名的类(或插件或模型)进行了特殊处理,并且没有对这些类所属的模块加以区分。比如:Module1_IndexController 类继承了Module1_BaseController类,yaf在分发的时候,会实例化这个控制器,自然也就会想办法加载它和Base,你可以在yaf_dispatcher.c中找到实例化控制器的函数,它叫做“yaf_dispatcher_get_controller”,并且被声明为:
zend_class_entry * yaf_dispatcher_get_controller(char *app_dir, char *module, char *controller, int len, int def_module TSRMLS_DC)
直观理解,传递app的目录,模块名、控制名、长度、默认控制器这些个参数,就可以了实例化控制器了。在这个函数中,实现了默认的控制器类命名规则:“控制器类名 = 控制器名Controller”(name_suffix默认值的情况下)。
而Module1_BaseController则是通过yaf_loader中的autoload自定加载的,yaf对控制器、插件和模型的差别化处理正是在这个autoload方法中实现的。所以,我们还得更改这个方法中对于模块处理的方式,来让php可以自动的找到Module1_BaseController类。
好了,知道命名规则的实现原理了,我们就有的放矢地修改这个命名规则。写到这里我不禁感叹鸟哥V5啊,所有我们用到的参数都帮我们准备妥当了:除了控制器名、模块名居然还有缺省模块名!
万事具备,只欠东风:
在yaf_dispatcher.c中的yaf_dispatcher_get_controller函数中找到如下代码:
if (YAF_G(name_suffix)) {class_len = spprintf(&class, 0, "%s%s%s", controller, YAF_G(name_separator), "Controller");} else {class_len = spprintf(&class, 0, "%s%s%s", "Controller", YAF_G(name_separator), controller);}
改为如下代码:
if (YAF_G(name_suffix)) {if (def_module){class_len = spprintf(&class, 0, "%s%s%s", controller, YAF_G(name_separator), "Controller");}else{class_len = spprintf(&class, 0, "%s%s%s%s%s", module, "_", controller, YAF_G(name_separator), "Controller");}} else {if (def_module){class_len = spprintf(&class, 0, "%s%s%s", "Controller", YAF_G(name_separator), controller);}else{class_len = spprintf(&class, 0, "%s%s%s%s%s", module, "_", "Controller", YAF_G(name_separator), controller);}}
代码的意思直白,不用多说。
下面是autoload方法的修改:
在yaf_loader.c中添加如下静态函数
/** {{{ static void yaf_loader_category_withmodule(char *class, uint file_name_len, char *directory, char *category TSRMLS_DC) */static void yaf_loader_category_withmodule(char ** file_name, uint file_name_len, char **directory, char *class_name, char *category TSRMLS_DC) {char *q, *p, *seg, *temp_classname = NULL, *app_directory;uint seg_len = 0 ,separator_len = 0;separator_len = YAF_G(name_separator_len);app_directory = YAF_G(directory);p = class_name;temp_classname = estrdup(class_name);q = p;while (1) {while(++q && *q != '_' && *q != '\0');if (*q != '\0') {seg_len= q - p;seg = estrndup(p, seg_len);temp_classname = estrdup(class_name + seg_len + 1);}break;}if(seg_len && (yaf_application_is_module_name(seg, seg_len TSRMLS_CC))){spprintf(directory, 0, "%s%c%s%c%s%c%s", app_directory, DEFAULT_SLASH,YAF_MODULE_DIRECTORY_NAME, DEFAULT_SLASH, seg, DEFAULT_SLASH, category);if (YAF_G(name_suffix)) {*file_name = estrndup(temp_classname, (file_name_len - seg_len - 1));} else {*file_name = estrdup(temp_classname + seg_len + separator_len + 1);}}}/* }}} */
这个函数实现对控制、插件和模型在命名上区分出模块并改变自定加载的目录。
然后在,autoload方法中找到形如“/* this is a controller class */”的注释,再在“break”语句之前的一行,添加如下代码:
yaf_loader_category_withmodule(&file_name, file_name_len, &directory, class_name, YAF_CONTROLLER_DIRECTORY_NAME TSRMLS_CC);
这行代码是对上面定义的函数的调用,以影响下文中加载的类名和加载目录。
好了,保存、重新make、目的达成!
亲测可用!O(∩_∩)O哈哈~
Think
整个过程中,总结了一下几个问题:
1、鸟哥的代码质量确实好
2、我的C语言功底确实烂
3、修改或编写C扩展,对于PHPer来说并不是想象的那么痛苦和困难,试着钻进去之后,你会发现:你爱PHP,你更爱C语言。
End
到目前为止,我还不了解鸟哥如此设计模块控制器命名规则的初衷,他有时间的话,一定找他问问明白。顺便向他推销一下文中所述的命名规则,毕竟像ZF靠拢一点的话,更容易拉ZF的粉丝过来用yaf。
另外在yaf的使用过程中,发现一个forward的问题,这个问题是:如果在控制器的init方法中forward,会导致apache(win)或php-fpm(linux)的崩溃,抽空也研究一下。
祝yaf越来越好。
- 关于yaf的控制器命名,一个纠结的问题。
- 关于yaf的控制器命名,一个纠结的问题(续)
- 关于servlet纠结的一个问题
- 一个纠结的问题
- 纠结的一个问题
- 关于yaf自动加载的一个疑惑
- 纠结得很的一个问题
- 很纠结的一个问题
- 一个很纠结的问题
- 记录一个纠结的问题
- 关于Java中BorderLayout布局的一个纠结问题,求教
- 关于DWR的某个纠结的问题
- 让我很纠结的一个问题
- php一个很纠结的问题---括号
- 关于Yaf的一些说明[转Yaf作者]
- 关于Yaf的一些说明[转Yaf作者]
- 【Yaf】Yaf的环境安装遇到的问题以及解决方案
- 纠结的一个晚上
- (转载)Linux OOM Killer个人总结
- java enum(枚举)使用详解 + 总结
- Android Runnable 运行在那个线程
- ios-multitasking-应用转入后台时,如何继续后台运行任务
- DMK指标源码
- 关于yaf的控制器命名,一个纠结的问题(续)
- ZOJ 1091 BFS
- vim使用大全[转]
- 错误:Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
- Android 在不知道ActivityName的情况下启动另一个程序
- uva 548 tree(中序后序还原树)
- 服务器端获取webservice客户端IP地址
- 在Windows下通过directshow录制屏幕的教程
- android java线程从入门到精通