文档章节

WordPress插件机制实现原理

阿唐
 阿唐
发布于 2013/12/18 21:07
字数 1783
阅读 1231
收藏 0

一直对软件的组件、插件架构非常感兴趣,我认为现在开发任何应用程序,一定要有一个架构良好的插件机制,这样可以吸引其他人来开发插件,极大的扩充系统的功能。Eclipse就是一个非常棒的例子,几乎你想什么功能,都可以从社区中找到相应的第三方插件。Firefox也同样如此,它的插件机制非常灵活(尤其是相对IE而言),因此Firefox社区中可以找到各种各样的插件。

1)WordPress读取所有可用的插件

  在文件“/wp-admin/includes/plugin.php”中,函数 get_plugins() 用来从文件系统得到所有的插件。原理很简单,就是读取“wp-content/plugins”目录下的所有PHP文件。这个函数允许一级的子文件夹,也就是说在’wp-content/plugins’下面的PHP文件,以及所以在此目录下的一级子文件夹内部的PHP文件被列作插件的候选,用下面的函数去进一步提取插件信息。这样的好处是方便用户利用文件夹来对插件进行管理和组织。而函数 get_plugin_data() 则用来得到插件的描述(Plugin Descriptor),主要包括插件的版本、名称、作者,等信息,而这些其实是以注释的方式存在的。用WordPress中自带的Hello插件来举例:

PHP代码
  • <?php   
  • /*  
  • Plugin Name: Hello Dolly  
  • Plugin URI: http://wordpress.org/#  
  • Description: This is not just a plugin, it symbolizes the hope and enthusiasm of an entire generation summed up in two words sung most famously by Louis Armstrong: Hello, Dolly. When activated you will randomly see a lyric from <cite>Hello, Dolly</cite> in the upper right of your admin screen on every page.  
  • Author: Matt Mullenweg  
  • Version: 1.5  
  • Author URI: http://ma.tt/  
  • */  
  • ?>  
  • 这样,在get_plugin_data函数中,就可以来得到插件的详细信息。

    PHP代码
  • <?php    
  • function get_plugin_data( $plugin_file ) {   
  •     $plugin_data = implode( ”, file( $plugin_file ));   
  •     preg_match( ‘|Plugin Name:(.*)$|mi’, $plugin_data, $plugin_name );   
  •     preg_match( ‘|Plugin URI:(.*)$|mi’, $plugin_data, $plugin_uri );   
  •     preg_match( ‘|Description:(.*)$|mi’, $plugin_data, $description );   
  •     preg_match( ‘|Author:(.*)$|mi’, $plugin_data, $author_name );   
  •     preg_match( ‘|Author URI:(.*)$|mi’, $plugin_data, $author_uri );   
  •     
  •     if ( preg_match( “|Version:(.*)|i”, $plugin_data, $version ))   
  •         $version = trim( $version[1] );   
  •     else  
  •         $version = ”;   
  •     
  •     $description = wptexturize( trim( $description[1] ));   
  •     
  •     $name = $plugin_name[1];   
  •     $name = trim( $name );   
  •     $plugin = $name;   
  •     if (” != trim($plugin_uri[1]) && ” != $name ) {   
  •         $plugin = ‘<a href=”‘ . trim( $plugin_uri[1] ) . ‘” title=”‘.__( ‘Visit plugin homepage’ ).‘”>’.$plugin.‘</a>’;   
  •     }   
  •     
  •     if (” == $author_uri[1] ) {   
  •         $author = trim( $author_name[1] );   
  •     } else {   
  •         $author = ‘<a href=”‘ . trim( $author_uri[1] ) . ‘” title=”‘.__( ‘Visit author homepage’ ).‘”>’ . trim( $author_name[1] ) . ‘</a>’;   
  •     }   
  •     
  •     return array(‘Name’ => $name, ‘Title’ => $plugin, ‘Description’ => $description, ‘Author’ => $author, ‘Version’ => $version);   
  • }   
  • ?>  
  • 2)启用 & 禁用插件

      启用(禁用)插件的操作都在Plugins.php中,比如我要Deactive “Hello”这个插件,最后的URL其实是这个样子:

    http://localhost/blog/wp-admin/plugins.php?action=deactivate&plugin=hello.php

      其中,“Action”表示动作,值为“active”或者“deactivate”,而“Plugin”表示动作的对象插件,此处为“hello.php”。得到动作指令后,首先从数据库中取出当前已经激活的插件。

    PHP代码
  • <?php $current = get_settings(‘active_plugins’); ?>  
  • 然后根据动作,重新生成已激活插件数组,存入数据库,并重新加载此页。加载的时候就需要考虑这些已经激活的插件是怎么工作的了。
    BTW:附上数据库的Options表中0插件和只有1个插件的值:
    没有插件:

    a:1:{i:0;s:0:”";}

    只有Hello插件:

    a:2:{i:0;s:0:”";i:1;s:9:”hello.php”;}

    3)如何加载启用的插件到系统中

    WordPress中的每页都会包含“wp-config.php”文件,而“wp-config.php”中也会自动加载“wp-settings.php”文件。在“wp-settings.php”文件中,可以找到以下与插件相关的代码片断:

    PHP代码
  • <?php    
  • if ( get_option(‘active_plugins’) ) {   
  •     $current_plugins = get_option(‘active_plugins’);   
  •     if ( is_array($current_plugins) ) {   
  •         foreach ($current_plugins as $plugin) {   
  •             if ( ” != $plugin && 0 == validate_file($plugin) && file_exists(WP_PLUGIN_DIR . ‘/’ . $plugin) )   
  •                 include_once(WP_PLUGIN_DIR . ‘/’ . $plugin);   
  •         }   
  •     }   
  • }   
  • ?>  
  • 可见,这段代码会取出系统中所有启用的插件,并包含进来。所以在每页加载的时候,都会首先包含这些插件代码。那么,这些插件自己在加载的时候都做了什么呢?

    4)插件的加载

      插件的加载其实最重要的一个部分就是插件的事件注册机制,WordPress插件中的事件注册其实和Eclipse中的扩展点(Extension-Point)机制非常相像,而这种类似“插销”、“插销座”的软件插拔方式也成为了最近软件组件架构方面应用最多的实践。
      事件注册过程中比较重要的几个函数分别是:do_action、add_action、add_filter。WordPress中默认定义了很多扩展点(也可以叫做“钩子”),或者说注册了很多系统事件(WP中的正规叫法应该是“Action Tag”),比如“admin_head”表示Admin页面的Head输出事件,“publish_post”表示发布一篇帖子的事件等等。而插件要做的就是扩展这些扩展点,或者说挂接这些钩子,从而实现系统的扩展功能。add_action就是通常插件扩展某个扩展点用到的函数,而do_action 是扩展点本身开始执行的函数。
      刚才说过WordPress中的每一页执行前都会Include所有Active的插件代码,而这些代码通常都会用“add_action”来将自己的函数注册到系统的扩展点中。这样,在扩展点执行的时候,就会找到系统中所有已经挂接到这个扩展点上的插件的函数来执行之,从而扩充系统的功能。
      WordPress中的很多功能也都是通过这种插件结构来实现的,默认注册了很多系统事件,都在’default-filter.php’中。比如:

    PHP代码
  • <?php add_action(‘publish_post’, ‘generic_ping’); ?>  
  • 这个是用来在发布每篇帖子的时候发送XML-RPC Ping的。再比如:

    PHP代码
  • <?php add_filter(‘the_content’, ‘convert_smilies’); ?>  
  • 用来将正文(content)中的笑脸符号转换为图像。
      还是举“Hello”插件来说。Hello插件会随机的在Admin Page的右上角显示一段话,它的工作原理是这样的:
      在每一个Admin page的前面都有

    PHP代码
  • <?php require_once(‘admin-header.php’); ?>  
  • 而在“admin-head.php”中将会执行扩展点“admin-head”的所有扩展: 

    PHP代码
  • <?php do_action(‘admin_head’, ”); ?>  
  • 这样,就会执行所有挂接到admin_head的函数,Admin Page 的 Footer 部分也是类似。

    5)如果插件中涉及UI

      其实是一样的。以WordPress FeedBurner Plugin中添加菜单为例。
      如果想添加一个菜单,就需要注册“admin_menu”这个Action Tag(系统事件)即可:

    PHP代码
  • <?php add_action(‘admin_menu’, ‘ol_add_feedburner_options_page’); ?>  
  • 插件中的这个函数为:

    PHP代码
  • <?php   
  • function ol_add_feedburner_options_page() {   
  •     if (function_exists(‘add_options_page’)) {   
  •         add_options_page(‘FeedBurner’, ‘FeedBurner’, 8, basename(__FILE__), ‘ol_feedburner_options_subpanel’);   
  •     }   
  • }   
  • ?>  
  • “add_options_page”这个函数就会在系统的“Options”菜单中添加“FeedBurner”这样一个子菜单。

    6)其它

      还有一些简单的插件就是只提供一些API函数。比如Most_Commented Plugin,它提供一个API “mdv_most_commented”:通过数据库查询得到评论最多的文章,并加以显示。因为这个插件已经被Include过,所以可以用这个API 来进行显示。

    © 著作权归作者所有

    阿唐
    粉丝 8
    博文 109
    码字总数 30130
    作品 1
    武汉
    程序员
    私信 提问
    [WordPress源码分析]插件配置更新

    WordPress有一套注册和修改配置的机制,很多插件设置都基于这套机制实现。以BAE-Helper为例,插件的配置都是通过wp-admin/options.php更新的,详见《[BAE-Helper]实现分析v0.1》。而具体Wor...

    joshuazhan
    2013/09/17
    739
    0
    基于开源WordPress的高校数字图书馆应用构建

    〔摘 要〕开源WordPress作为博客网站建设广泛使用的平台,也应用在了内容管理系统、电子商务、社交网络等各个方面。WordPress包含了众多的web 2.0功能特性,使其在高校数字图书馆各种服务建设...

    james_laughing
    2018/05/21
    130
    0
    一个php做的系统,插件机制怎么实现?

    一个php做的系统,插件机制怎么实现? 想discuz,wordpress都可以有插件,是怎么实现的,什么思想?

    OSC首席键客
    2013/10/15
    544
    4
    WordPress代码实现相关文章的几种方法

    WordPress很多插件可以实现相关文章的功能,插件的优点是配置简单,但是可能会对网站的速度造成一些小的影响,所以很多人还是比较喜欢用 代码实现需要的功能,但是话又说回来了,代码实现也有...

    西西爱OS
    2012/10/20
    84
    0
    快讯:WordPress 插件下载超过一亿次

    来自 WordPress 官方的博客称,其开发团队目前对 WordPress 的插件库中超过 10000 个插件进行下载统计,目前总共有超过 1 亿次的插件下载次数,同时 WordPress 3.0 已经有超过 300万次下载。...

    红薯
    2010/07/03
    567
    0

    没有更多内容

    加载失败,请刷新页面

    加载更多

    Excel导入数据库数据+Excel导入网页数据【实时追踪】

    1.Excel导入数据库数据:数据选项卡------>导入数据 2.Excel导入网页数据【实时追踪】:

    东方墨天
    33分钟前
    4
    1
    正则表达式如何匹配一个单词存在一次或零次并且不占捕获组位置

    正则表达式如何匹配一个单词存在一次或零次并且不占捕获组位置 今天要用正则表达式实现匹配一个词出现一次或者不出现的情况,但是又不仅仅是这么简单的需求。先详细说下我这种情况吧,也许有...

    Airship
    39分钟前
    5
    0
    第八讲:asp.net C# web 读取文件

    本讲主要讲解如何在asp.net页面上传文件。 首先,前台页面: 其次,后台页面: 结果: 1、前台效果: 2、后台结果:

    刘日辉
    51分钟前
    5
    0
    提炼问题域

    2.1 知识提炼与协作 知识提炼是从问题域中提炼出相关信息的技术,其目的是构建能够满足业务用例需求的有用模型。 知识提炼是为技术团队在基于一组需求为问题域设计解决方案时弥补所欠缺的知识...

    细节探索者
    59分钟前
    5
    0
    redis是单线程,为什么那么快

    完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。 数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的。 采用单线程,避免了不必要的上下文切换和竞争条件,也不存...

    DustinChan
    今天
    6
    0

    没有更多内容

    加载失败,请刷新页面

    加载更多

    返回顶部
    顶部