2010年11月19日 星期五 下午 02:31 runhooks()函数从名字来分析也是加载插件的,也是二次开发中最为重要的环节!也是哥之所以分析代码的初衷! 开始之前,先介绍一下上下文环境,首先从帖子标题可以看出是在广场栏目中,然后是我只开启了“马甲”插件(默认自带的)。杯具的是貌似BBS首页似乎不会激活这个插件!我还没测试BBS的其他子模块!不过大概看了一下这个函数的代码,还是有章法可循的!下面我就个人的理解试着分析一下! function runhooks() { global $_G; if(defined('CURMODULE')) { hookscript(CURMODULE, $_G['basescript']); if(($do = !empty($_G['gp_do']) ? $_G['gp_do'] : (!empty($_GET['do']) ? $_GET['do'] : ''))) { hookscript(CURMODULE, $_G['basescript'].'_'.$do); } } } 就这个函数本身而言,其实没几行代码,不过核心逻辑都在hookscript()里,所以它就显的很单薄!可以看的出来,插件依赖CURMODULE,$_G['basecript'],$_G['gp_do'],$_GET['do']这几个值,把它们拼装起来可以用于在$_G['setting']['hookscript']多维数组中定位要加载的插件信息! 这里要回忆一下$discuz->init()的运行过程,其中的_init_setting()的相关代码如下: if($this->init_setting) { if(empty($this->var['setting'])) { $this->cachelist[] = 'setting'; } 这部分的内容我在先前的相关帖中已经分析过了,不明白的朋友可以哥的空间内搜索帖子! 大家可以利用debug追踪一下数据,我贴出我的这个$_G['setting']['hookscript']数据结构: 老实说,这张图没太大的利用价值,至少就目前的上下文环境,是匹配不到合适的插件的! 不过还是可以让我们了解它的大致结构,有利于下面的代码分析! 下面就开始分析一下hookscript()这个很重要的函数,先看一下它的参数表: function hookscript($script, $hscript, $type = 'funcs', $param = array(), $func = '') $script指明了此插件在哪个模块执行(其实就是$mod,理解成动作比较顺口); $hscript指明了此插件属于哪个板块(form,gropu,member,misc,plugin,portal,userapp,search等,每个都对应一个入口文件); $type指明了此插件的调用类型(这个我也拿不准,错了表怪俺); $param提供调用此插件方法时需要传递的参数; $func指明了要调用此插件的哪些可执行方法。 再看它的内部代码,注意static $pluginclasses;作用不用多说了吧? 我暂时还不清楚为什么要有下面这个操作: if(!isset($_G['cache']['plugin'])) { loadcache('plugin'); } 加载plugin缓存的作用是什么哪?我估计后面的分析中会揭开这个疑问! 出除此之外,这个函数就没什么难点了吧? 再贴出来一行比较重要的代码: $return = $pluginclasses[$classkey]->$hookfunc[1]($param); 最后把插件指定方法的返回值存入$_G['setting']['pluginhooks'][$hookkey]中!! 还有一个重点是:插件的标识符($hooksadminid[$identifier])很重要,通过它可以决定是否加载该插件的文件,从而决定是否激活该插件! 细心的朋友应该注意到在上面的图中,有看到一个global配置数组吧?从名字判断,它应该指定的是全局要加载的插件,可是我花了老大劲儿在代码里翻腾,怎么也找不到这全局插件的调用位置!不过,最后总算让俺捕捉到了一些痕迹,在模板文件的头部有一个函数调用代码:hookscriptoutput('discuz')! function hookscriptoutput($tplfile) { global $_G; hookscript('global', 'global'); if(defined('CURMODULE')) { $param = array('template' => $tplfile, 'message' => $_G['hookscriptmessage'], 'values' => $_G['hookscriptvalues']); hookscript(CURMODULE, $_G['basescript'], 'outputfuncs', $param); if(($do = !empty($_G['gp_do']) ? $_G['gp_do'] : (!empty($_GET['do']) ? $_GET['do'] : ''))) { hookscript(CURMODULE, $_G['basescript'].'_'.$do, 'outputfuncs', $param); } } } 不用解释了吧,这就是执行全局插件的赤裸裸的证据! 好,到此为止就算简单的分析完了runhooks()函数,可能还有很多内幕没有挖掘!不过别着急,慢慢来! 最后重申,哥之所以看DX的代码,就是为了深刻的理解它的插件机制!所以以后肯定还会有插件的帖子,到时候再更深层次的去分析! 到此为止,就结贴了唷~~下次见~