WordPress插件工作机制

文章目录

因为想自己制作一个插件,所以需要了解一下WordPress的插件工作机制。以方便后来查阅使用。

WordPress读取所有可用的插件

在文件“/wp-admin/includes/plugin.php”中,有两类函数用来读取插件信息。

get_plugins()函数
用来从文件系统得到所有的插件。原理很简单,就是读取“wp-content/plugins”目录下的所有PHP文件。这个函数允许一级的子文件夹,也就是说在’wp-content/plugins’下面的PHP文件(说明他们没有把插件写入数据库),以及所以在此目录下的一级子文件夹内部的PHP文件被列作插件的候选。

get_plugin_data()函数
用来得到插件的描述(Plugin Descriptor),主要包括插件的版本、名称、作者,等信息,而这些其实是以注释的方式存在的。

用WordPress中自带的Hello插件(插件放在wp-content/plugins/hello.php,在最后有这样一行代码:add_action(‘admin_head’, ‘dolly_css’);,后面有用,先提醒大家注意下)来举例:

1
2
3
4
5
6
7
8
/*
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函数中,就可以来得到插件的详细信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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 title="'.__( 'Visit plugin homepage' ).'" href="' . trim( $plugin_uri[1] ) . '">'.$plugin.'</a>';
    }
 
    if ('' == $author_uri[1] ) {
        $author = trim( $author_name[1] );
    } else {
        $author = '<a title="'.__( 'Visit author homepage' ).'" href="' . trim( $author_uri[1] ) . '">' . trim( $author_name[1] ) . '</a>';
    }
 
   return array('Name' => $name, 'Title' => $plugin, 'Description' => $description, 'Author' => $author, 'Version' => $version);

启用和禁用插件

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

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

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

1
$current = get_settings('active_plugins');

然后根据动作,重新生成已激活插件数组,存入数据库,并重新加载此页。加载的时候就需要考虑这些已经激活的插件是怎么工作的了。

附上数据库的Options表中插件和只有1个插件的值:

没有启用插件时 option 表 字段名为 option_name 值为 active_plugins 对应的 option_value 字段值为(SQL查看:SELECT option_value FROM wp_option WHERE option_name=’active_plugins’):

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

只启用 Hello 插件时:

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

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

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

1
2
3
4
5
6
7
8
9
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);
         }
     }
}

可见,这段代码会取出系统中所有启用的插件,并把插件文件包含进来。所以在每页加载的时候,都会首先包含这些插件代码。那么,这些插件自己在加载的时候都做了什么呢?请看下面

插件的加载

插件的加载其实最重要的一个部分就是插件的事件注册机制,WordPress插件中的事件注册其实和Eclipse中的扩展点机制非常相像。

事件注册过程中比较重要的几个函数分别是:add_action、add_filter。WordPress中默认定义了很多扩展点(也可以叫做“钩子”,这些“钩子”大部分的可以在 wp-includes/default-filters.php 文件里面查看到),或者说注册了很多系统事件(WP中的正规叫法应该是“Action Tag”),比如“admin_head”表示Admin页面的Head输出事件,“publish_post”表示发布一篇帖子的事件等等。而插件要做的就是扩展这些扩展点,从而实现系统的扩展功能。add_action就是通常插件扩展某个扩展点用到的函数。

刚才说过WordPress中的每一页执行前都会Include所有Active的插件代码,而这些代码都会用“add_action”来将自己的函数注册到系统的扩展点中。这样,在扩展点执行的时候,就会找到系统中所有已经挂接到这个扩展点上的插件的函数来执行之,从而扩充系统的功能。

比如用来在发布每篇帖子的时候发送XML-RPC Ping:

1
add_action('publish_post', 'generic_ping');

比如用来将正文(content)中的笑脸符号转换为图像:

1
add_filter('the_content', 'convert_smilies');

还是举“Hello”插件来说。Hello插件会随机的在Admin Page的右上角显示一段话,它的工作原理是这样的:

在每一个Admin page的前面都有

1
require_once('admin-header.php');

而在“admin-head.php”中你会发现它这样一行代码:

1
do_action('admin_head');//大概在60行左右

这样,就会通过do_action函数里面的‘_wp_call_all_hook’函数 ,将所有通过add_action 函数挂接到admin_head ‘钩子’上的所有函数(包括上面通过 Hello Dolly 挂接上去的dolly_css等函数)执行,Admin Page 的 Footer 部分也是类似。

插件中涉及UI

其实是一样的。以WordPress FeedBurner Plugin中添加菜单为例。

如果想添加一个菜单,就需要注册“admin_menu”这个Action Tag(系统事件)即可:

1
add_action('admin_menu', 'ol_add_feedburner_options_page');

插件中的这个函数为:

1
2
3
4
5
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”这样一个子菜单。

其它

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

参考文章:WordPress 插件实现机制



本文出自 TENNFY WU,转载时请注明出处及相应链接。

本文永久链接: http://www.tennfy.com/1576.html

下一篇文章:

上一篇文章:

7人参与了讨论

  1. Youth.霖 说:

    我改写过多莉成了中文歌词,研究了一下下钩子hook,然后基本的代码就看懂了。。。

  2. FINLE 说:

    了解了。
    但,用不上。

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

3 + 5 = ?


您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

返回顶部