+ -
当前位置:首页 → 问答吧 → 偶来说说ThinkPHP【插件】原理

偶来说说ThinkPHP【插件】原理

时间:2009-04-02

来源:互联网



把TP的源码看了一遍,先把与插件有关的摘出来,大家分享,讨论一下。。。
(说下感受,感觉整个过程和Wordpress的插件机制还是很像的。。。)
1、首先说下,TP的插件是在哪个地方载入的
App.class.php

  1.     private function loadPlugIn()
  2.     {
  3.         // 加载插件必须的函数
  4.         include THINK_PATH.'/Common/plugin.php';
  5.         //加载有效插件文件
  6.         if(is_file(RUNTIME_PATH.'~plugins.php')) {
  7.             include RUNTIME_PATH.'~plugins.php';
  8.         }else{
  9.             // 检查插件数据
  10.             $common_plugins = get_plugins(THINK_PATH.'/PlugIns','Think');// 公共插件
  11.             $app_plugins = get_plugins();// 项目插件
  12.             // 合并插件数据
  13.             $plugins    = array_merge($common_plugins,$app_plugins);
  14.             // 缓存插件数据
  15.             $content = '';
  16.             foreach($plugins as $key=>$file) {
  17.                 include $file;
  18.                 $content .= php_strip_whitespace($file);
  19.             }
  20.             file_put_contents(RUNTIME_PATH.'~plugins.php',$content);
  21.         }
  22.         return ;
  23.     }
复制代码
其中的这句
  1. include $val['file'];   
复制代码
就把TP的核心和项目下的PlugIns目录下的文件给包含进来了
2、把插件的函数名和参数个数放入SESSION中,就是这个函数了
  1. /**
  2. +----------------------------------------------------------
  3. * 动态添加过滤器
  4. +----------------------------------------------------------
  5. * @param string $tag 过滤器标签
  6. * @param string $function 过滤方法名
  7. * @param integer $priority 执行优先级
  8. * @param integer $args 参数
  9. +----------------------------------------------------------
  10. * @return boolean
  11. +----------------------------------------------------------
  12. */
  13. function add_filter($tag,$function,$priority = 10,$args = 1)
  14. {
  15.     static $_filter = array();
  16.     if ( isset($_filter[APP_NAME.'_'.$tag]["$priority"]) ) {
  17.         foreach($_filter[APP_NAME.'_'.$tag]["$priority"] as $filter) {
  18.             if ( $filter['function'] == $function ) {
  19.                 return true;
  20.             }
  21.         }
  22.     }
  23.     $_filter[APP_NAME.'_'.$tag]["$priority"][] = array('function'=> $function,'args'=> $args);
  24.     $_SESSION['_filters']   =   $_filter;
  25.     return true;
  26. }
复制代码
执行完,SESSION中会有如此的形式
  1. array(6) {
  2.   ["_filters"] => array(3) {
  3.     ["Example_app_init"] => array(1) {
  4.       [10] => array(2) {
  5.         [0] => array(2) {
  6.           ["function"] => string(9) "varFilter"
  7.           ["args"] => int(1)
  8.         }
  9.         [1] => array(2) {
  10.           ["function"] => string(14) "checkViewCache"
  11.           ["args"] => int(1)
  12.         }
  13.       }
  14.     }
  15.    .........
复制代码
3、执行插件
通过session中的_filters对应的值,来查找函数,并执行
apply_filter('app_init');
  1. /**
  2. +----------------------------------------------------------
  3. * 执行过滤器
  4. +----------------------------------------------------------
  5. * @param string $tag 过滤器标签
  6. * @param string $string 参数
  7. +----------------------------------------------------------
  8. * @return boolean
  9. +----------------------------------------------------------
  10. */
  11. function apply_filter($tag,$string='')
  12. {
  13.     if (!isset($_SESSION['_filters']) ||  !isset($_SESSION['_filters'][APP_NAME.'_'.$tag]) ) {
  14.         return $string;
  15.     }
  16.     $_filter  = $_SESSION['_filters'][APP_NAME.'_'.$tag];
  17.     ksort($_filter);
  18.     $args = array_slice(func_get_args(), 2);
  19.     foreach ($_filter as $priority => $functions) {
  20.         if ( !is_null($functions) ) {
  21.             foreach($functions as $function) {
  22.                 if(is_callable($function['function'])) {
  23.                     $args = array_merge(array($string), $args);
  24.                     $string = call_user_func_array($function['function'],$args);
  25.                 }
  26.             }
  27.         }
  28.     }
  29.     return $string;
  30. }
复制代码
4、如何写自己的插件
如果你能看懂上面,我想写个插件应该不难了吧。。
我举个例子,大家参考下:
(1)在自己项目的Plugins目录下新建say.php,内容如下
  1. <?php
  2. function test ($con)
  3. {
  4.   echo $con;
  5. }
  6. add_filter('Say','test');
  7. ?>
复制代码
(2)在config.php中加一句
  1. 'THINK_PLUGIN_ON' =>true,
复制代码
然后,清缓存
(3)调用
  1.     public function index(){
  2.          dump($_SESSION["_filters"]);
  3.          apply_filter('Say',"hi");
  4.     }
复制代码
输出:

作者: fantasy   发布时间: 2009-04-02

不错  支持哈~~!

作者: thinkcms   发布时间: 2009-04-02

学习一下,精品帖子,谢楼主了!

作者: leon_studio   发布时间: 2009-04-03

新版这块还是有很大改进的。。。大家期待吧。。。~~~

作者: fantasy   发布时间: 2009-04-03

在参照yBlog的插件。。。

作者: 小坏虾   发布时间: 2009-04-04

不错,顶一个。

作者: freebirdy   发布时间: 2009-04-04

顶一个!

作者: sunsmile   发布时间: 2009-07-01

顶一个。

作者: qq23154623   发布时间: 2009-08-17

顶,不错

作者: xmjlgh   发布时间: 2009-08-18

很不错的思路

作者: 123133   发布时间: 2009-08-19

强人,有空教教

作者: cheseboy2000   发布时间: 2009-08-19

不知道新版本会改成么样

作者: eilf2   发布时间: 2009-08-19

不错,
oooO ↘┏━┓ ↙ Oooo
( 踩)→┃你┃ ←(死 )
  \ ( →┃√┃ ← ) /
  \_)↗┗━┛ ↖(_/

作者: aibangde   发布时间: 2009-08-20

不错哈

作者: lcyhoho   发布时间: 2009-08-27

不懂                      

作者: xiaogg   发布时间: 2009-08-27

不错,顶一个。

作者: jun708   发布时间: 2009-08-27

顶,不错

作者: steptt   发布时间: 2009-08-29

不错,支持

作者: mathsfox   发布时间: 2009-08-29

2.0 不是这样吧?  我没有找到你说的

作者: imeagle   发布时间: 2010-03-01

这个要学习一下。 谢谢了。。。

作者: tomclub   发布时间: 2010-04-22

学习中.....

作者: whl1295a   发布时间: 2010-04-22

不错!学习了

作者: jintingbo   发布时间: 2010-05-16

mark...................................

作者: lovemdb   发布时间: 2010-06-20

最新版好像没有这个东东了啊

作者: diomen   发布时间: 2011-09-28