Dissect WordPress Plugin

ä¸€ç›´å¯¹è½¯ä»¶çš„ç»„ä»¶ã€æ’ä»¶æž¶æž„éžå¸¸æ„Ÿå…´è¶£ï¼Œæˆ‘认为现在开å‘任何应用程åºï¼Œä¸€å®šè¦æœ‰ä¸€ä¸ªæž¶æž„良好的æ’件机制,这样å¯ä»¥å¸å¼•其他人æ¥å¼€å‘æ’件,æžå¤§çš„æ‰©å……系统的功能。Eclipse就是一个éžå¸¸æ£’的例å­ï¼Œå‡ ä¹Žä½ æƒ³ä»€ä¹ˆåŠŸèƒ½ï¼Œéƒ½å¯ä»¥ä»Žç¤¾åŒºä¸­æ‰¾åˆ°ç›¸åº”的第三方æ’件。Firefoxä¹ŸåŒæ ·å¦‚此,它的æ’件机制éžå¸¸çµæ´»ï¼ˆå°¤å…¶æ˜¯ç›¸å¯¹IE而言),因此Firefox社区中å¯ä»¥æ‰¾åˆ°å„ç§å„æ ·çš„æ’件。

å°±åƒNat在Open Source Summit中的一å¥è¯ï¼š

You have to give people work to do.
Create an “architecture of participation†as Tim O’Reilly says.

自从开始使用WordPress,就想学习学习WordPress强大的æ’ä»¶æœºåˆ¶ã€‚ä»¥å‰æ›¾ç»ç ”究过的COMã€XPCOMã€Firefox Extensionsã€Eclipse Plugin都是桌é¢åº”用级别的组件结构,而对Web应用中的æ’件确实知之甚少,于是,Dissect了一下WordPress(1.5.1.3)。虽然对PHP䏿˜¯å¾ˆç†Ÿæ‚‰ï¼Œä¸è¿‡çœ‹çœ‹æºç è¿˜æ˜¯é—®é¢˜ä¸å¤§ã€‚

1)WordPressè¯»å–æ‰€æœ‰å¯ç”¨çš„æ’ä»¶

在文件“admin-functions.phpâ€ä¸­ï¼Œå‡½æ•°

<?php function get_plugins() ?> ?>

用æ¥ä»Žæ–‡ä»¶ç³»ç»Ÿå¾—到所有的æ’件。原ç†å¾ˆç®€å•,就是读喒wp-content/plugins’目录下的所有PHP文件。这个函数å…è®¸ä¸€çº§çš„å­æ–‡ä»¶å¤¹ï¼Œä¹Ÿå°±æ˜¯è¯´åœ¨’wp-content/plugins’下é¢çš„PHPæ–‡ä»¶ï¼Œä»¥åŠæ‰€ä»¥åœ¨æ­¤ç›®å½•ä¸‹çš„ä¸€çº§å­æ–‡ä»¶å¤¹å†…部的PHP文件被列作æ’件的候选,用下é¢çš„函数去进一步æå–æ’ä»¶ä¿¡æ¯ã€‚这样的好处是方便用户利用文件夹æ¥å¯¹æ’件进行管ç†å’Œç»„织。

而函数

<?php function get_plugin_data() ?>

用æ¥å¾—到æ’ä»¶çš„æè¿°ï¼ˆPlugin Descriptor),主è¦åŒ…括æ’件的版本ã€åç§°ã€ä½œè€…,等信æ¯ï¼Œè€Œè¿™äº›å…¶å®žæ˜¯ä»¥æ³¨é‡Šçš„æ–¹å¼å­˜åœ¨çš„。用WordPress中自带的Helloæ’ä»¶æ¥ä¸¾ä¾‹ï¼š

<?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 ... Author: Matt Mullenweg Version: 1.0 Author URI: http://photomatt.net/  ?>

这样,在get_plugin_data函数中,就å¯ä»¥æ¥å¾—到æ’件的详细信æ¯ã€‚

<?php  function get_plugin_data($plugin_file) {     $plugin_data = implode('', file($plugin_file));     preg_match("|Plugin Name:(.*)|i", $plugin_data, $plugin_name);     preg_match("|Plugin URI:(.*)|i", $plugin_data, $plugin_uri);     preg_match("|Description:(.*)|i", $plugin_data, $description);     preg_match("|Author:(.*)|i", $plugin_data, $author_name);     preg_match("|Author URI:(.*)|i", $plugin_data, $author_uri);  ?>

2)Active & Deactive Plugin

Active(Deactive)æ’ä»¶çš„æ“作都在Plugins.php中,比如我è¦Deactive “Helloâ€è¿™ä¸ªæ’件,最åŽçš„URL其实是这个样å­ï¼š

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

其中,“Actionâ€è¡¨ç¤ºåŠ¨ä½œï¼Œå€¼ä¸ºâ€œactiveâ€æˆ–者“deactivateâ€ï¼Œè€Œâ€œPluginâ€è¡¨ç¤ºåŠ¨ä½œçš„å¯¹è±¡æ’件,此处为“hello.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)æ’件(Active)如何加载到系统中

WordPress中的æ¯é¡µéƒ½ä¼šåŒ…å«â€œwp-config.phpâ€æ–‡ä»¶ï¼Œè€Œåœ¨â€œwp-config.phpâ€çš„æœ€åŽæœ‰è¿™æ ·ä¸€å¥ï¼š

<?php require_once(ABSPATH.'wp-settings.php'); ?>

在“wp-settings.phpâ€æ–‡ä»¶ä¸­ï¼Œå¯ä»¥æ‰¾åˆ°ä»¥ä¸‹ä¸Žæ’件相关的代ç ç‰‡æ–­ï¼š

<?php  if ( get_settings('active_plugins') ) {     $current_plugins = get_settings('active_plugins');     if ( is_array($current_plugins) ) {         foreach ($current_plugins as $plugin) {             if ('' != $plugin && file_exists(ABSPATH . 'wp-content/plugins/' . $plugin))                 include_once(ABSPATH . 'wp-content/plugins/' . $plugin);         }     } }  ?>

å¯è§ï¼Œè¿™æ®µä»£ç ä¼šå–出系统中所有Activeçš„æ’件,并Includeè¿›æ¥ã€‚所以在æ¯é¡µåŠ è½½çš„æ—¶å€™ï¼Œéƒ½ä¼šé¦–å…ˆInclude这些æ’件代ç ã€‚那么,这些æ’件自己在加载的时候都åšäº†ä»€ä¹ˆå‘¢ï¼Ÿ

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 add_action('publish_post', 'generic_ping'); ?>

这个是用æ¥åœ¨å‘布æ¯ç¯‡å¸–å­çš„æ—¶å€™å‘é€XML-RPC Pingçš„ã€‚å†æ¯”如:

<?php add_filter('the_content', 'convert_smilies'); ?>

用æ¥å°†æ­£æ–‡ï¼ˆcontent)中的笑脸符å·è½¬æ¢ä¸ºå›¾åƒã€‚

还是举“Helloâ€æ’ä»¶æ¥è¯´ã€‚Helloæ’ä»¶ä¼šéšæœºçš„在Admin Pageçš„å³ä¸Šè§’显示一段è¯ï¼Œå®ƒçš„å·¥ä½œåŽŸç†æ˜¯è¿™æ ·çš„:

在æ¯ä¸€ä¸ªAdmin pageçš„å‰é¢éƒ½æœ‰

<?php require_once('admin-header.php'); ?>

而在“admin-head.phpâ€ä¸­å°†ä¼šæ‰§è¡Œæ‰©å±•点“admin_headâ€çš„æ‰€æœ‰æ‰©å±•:

<?php  do_action('admin_head', '');  ?>

这样,就会执行所有挂接到admin_head的函数

Admin Pageçš„Footeréƒ¨åˆ†åŒæ ·å¦‚此,

<?php  do_action('admin_footer', '');  ?>

这样,就会执行所有挂接到admin_footer的函数

冿¥çœ‹çœ‹Helloæ’ä»¶çš„åˆå§‹åŒ–过程中:

<?php    // This just echoes the chosen line, we'll position it later function hello_dolly() {     global $chosen;     echo "<p id='dolly'>$chosen</p>"; }   // Now we set that function up to execute when the admin_footer action is called add_action('admin_footer', 'hello_dolly');   // We need some CSS to position the paragraph function dolly_css() {     echo "     <style type='text/css'>     #dolly {         position: absolute;         top: 5px; margin: 0; padding: 0;         right: 3em;         font-size: 20px;         color: #f66;     }     </style>     "; }   add_action('admin_head', 'dolly_css');   ?>

å¯è§ï¼Œå°†dollyçš„CSS部分æ’到Header部分,而在footer部分æ’入显示代ç ï¼Œè¿™æ ·ï¼Œåœ¨AdminPageçš„å³ä¸Šè§’å°±ä¼šéšæœºæ˜¾ç¤ºä¸€æ®µè¯ã€‚

冿¥çœ‹çœ‹æ›¾ç»è¯´è¿‡çš„Google Sitemapæ’件,æ’件中有一项功能是在å‘布ã€ä¿®æ”¹æˆ–è€…åˆ é™¤æ–‡ç« çš„æ—¶å€™é‡æ–°Build Sitemap文件,这个功能就是通过注册系统的三个事件(“publish_postâ€ï¼Œâ€œedit_postâ€ï¼Œâ€œdelete_postâ€ï¼‰æ¥å®Œæˆçš„。

<?php  //Register to various events... @WordPress Dev Team: I wish me a 'public_content_changed' action :) if(defined("SM_ACTIVE") && SM_ACTIVE===true) {     //If a new post gets published     add_action('publish_post', 'sm_buildSitemap');       //Existing post gets edited (published or not)     add_action('edit_post', 'sm_buildSitemap');       //Existing posts gets deleted (published or not)     add_action('delete_post', 'sm_buildSitemap'); } #endregion  ?>

BTWï¼šå…¶ä¸­çš„æ³¨é‡Šä¹Ÿå¾ˆæœ‰æ„æ€ï¼Œæˆ‘ä¹Ÿè§‰å¾—ç¡®å®žéœ€è¦æœ‰â€œpublic_content_changedâ€è¿™æ ·ä¸€ä¸ªäº‹ä»¶ï¼Œå°±ä¸å¿…分别订阅三个å•独的事件了。

对了,就在我们刚æ‰è¯´çš„wp-settings.php中的æ’ä»¶å¯åЍåŽï¼Œæœ‰

<?php do_action('plugins_loaded'); ?>

这样一个系统事件,å¯ä»¥æ³¨å†Œè¿™ä¸ªäº‹ä»¶æ¥åšä¸€äº›å¸Œæœ›åœ¨æ‰€æœ‰æ’ä»¶Load完毕而åšçš„事儿。

5)如果æ’件中涉åŠUI

其实是一样的。以WordPress FeedBurner Plugin中添加èœå•为例:

如果想添加一个èœå•ï¼Œå°±éœ€è¦æ³¨å†Œâ€œadmin_menuâ€è¿™ä¸ªAction Tag(系统事件):

<?php add_action('admin_menu', 'ol_add_feedburner_options_page') ?>

å³å¯ï¼Œæ’件中的这个函数为:

<?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');   }<br>}  ?>

“add_options_pageâ€è¿™ä¸ªå‡½æ•°å°±ä¼šåœ¨ç³»ç»Ÿçš„“Optionsâ€èœå•中添加“FeedBurnerâ€è¿™æ ·ä¸€ä¸ªå­èœå•。

而这个函数其实就是增加 Menu 或者 SubMenu,

<?php  function add_submenu_page($parent, $page_title, $menu_title, $access_level, $file, $function = '') {     global $submenu;     global $menu;       $parent = plugin_basename($parent);     $file = plugin_basename($file);       // If the parent doesn't already have a submenu, add a link to the parent     // as the first item in the submenu.  If the submenu file is the same as the     // parent file someone is trying to link back to the parent manually.  In     // this case, don't automatically add a link back to avoid duplication.     if (! isset($submenu[$parent]) && $file != $parent) {         foreach ($menu as $parent_menu) {             if ($parent_menu[2] == $parent) {                 $submenu[$parent][] = $parent_menu;             }         }     }         $submenu[$parent][] = array($menu_title, $access_level, $file, $page_title);       $hookname = get_plugin_page_hookname($file, $parent);     if ( !empty($function) && !empty($hookname) )         add_action($hookname, $function);       return $hookname; }   function add_options_page($page_title, $menu_title, $access_level, $file, $function = '') {     return add_submenu_page('options-general.php', $page_title, $menu_title, $access_level, $file, $function); }  ?>

6)其它

还有一些简å•çš„æ’ä»¶å°±æ˜¯åªæä¾›ä¸€äº›API函数。比如Most_Commented Plugin,它æä¾›ä¸€ä¸ªAPI “mdv_most_commentedâ€ï¼šé€šè¿‡æ•°æ®åº“查询得到评论最多的文章,并加以显示。因为这个æ’ä»¶å·²ç»è¢«Include过,所以å¯ä»¥ç”¨è¿™ä¸ªAPIæ¥è¿›è¡Œæ˜¾ç¤ºã€‚

历å²ï¼š

2005.07.14 - 创建

2005.07.16 - 新增get_pluginsçš„å­æ–‡ä»¶å¤¹è§£æžéƒ¨åˆ†

Popularity: 40%

Related entries:

No Related Posts

7 Responses to “Dissect WordPress Plugin”

Meng Yan ( 孟岩 ) @ Weblog » Blog Archive » My WordPress Plugins Says:

[…] 当你的Blogæ—¥æ¸ä¸°å¯Œï¼Œå¯ä»¥è€ƒè™‘è®©é‚£äº›é™ˆå¹´è€æ–‡å‡ºæ¥æ™’晒太阳,就用这个Random Postå°±ä¸é”™ã€‚相信看了WordPressçš„æ’件结构,就能明白这个æ’件的基本原ç†ã€‚ […]

Meng Yan ( 孟岩 ) @ Weblog » Blog Archive » Dissect WordPress Themes Says:

[…] è¦æƒ³çœŸæ­£æˆåŠŸï¼Œå¿…é¡»èƒ½å¤Ÿæä¾›ä¸€ä¸ªå¯ä»¥ä¾›äººå‚与的架构,Eclipse如此,Firefox亦如此。与Plugin一样,WordPress中的Theme机制也éžå¸¸çµæ´»å’Œå¼ºå¤§ï¼Œç¤¾åŒºè´¡çŒ®å‡ºçš„一个个漂亮的Theme都是这个良好架构下的æ°ä½œã€‚ […]

GoTop’s Blog » Blog Archive » 两篇关于 WordPressçš„pluginå’Œtheme原ç†çš„æ–‡ç«  Says:

[…] http://www.mengyan.org/blog/archives/2005/07/14/32.html […]

Louis Says:

Hello,
Just wondering if anyone could help. I did something stupid and started my blog using a numerical archive system, and now I'd like to change it so that the post title is part of the URL for SEO reasons. Is there any Wordpress plugins that anyone knows of that could switch it without sending Googlers to invalid pages? Maybe some sort of redirector to the correct page?

Thanks.

GAOZHI BLOG » Blog Archive » Dissect WordPress Plugin(深入剖æžWordPressæ’件机制) Says:

[…] 还有一些简å•çš„æ’ä»¶å°±æ˜¯åªæä¾›ä¸€äº›API函数。比如Most_Commented Plugin,它æä¾›ä¸€ä¸ªAPI “mdv_most_commentedâ€ï¼šé€šè¿‡æ•°æ®åº“查询得到评论最多的文章,并加以显示。因为这个æ’ä»¶å·²ç»è¢«Include过,所以å¯ä»¥ç”¨è¿™ä¸ªAPIæ¥è¿›è¡Œæ˜¾ç¤ºã€‚ æ–‡ç« æ¥æº:http://www.mengyan.org/blog/archives/2005/07/14/32.html Leave a Comment […]

出家如åˆï¼Œæˆä½›æœ‰ä½™ » Dissect WordPress Plugin Says:

[…] http://www.mengyan.org/blog/archives/2005/07/14/32.html […]

WordPressçš„ä¸€äº›å·¥ä½œåŽŸç† | 失è½çš„神庙 Says:

[…] Dissect WordPress Plugin ç†è§£wordpressçš„æ’件机制 […]

Leave a comment

(required)

(required)


Information for comment users
Line and paragraph breaks are implemented automatically. Your e-mail address is never displayed. Please consider what you're posting.

Use the buttons below to customise your comment.


RSS feed for comments on this post | TrackBack URI

 

Creative Commons License
This work is licensed under a Creative Commons License.

爱情åƒé²œèŠ±ï¼Œå®ƒä»Žä¸å¼€æ”¾ï¼Œæ¬²æœ›åƒé‡Žè‰ï¼Œå®ƒç–¯ç‹‚的生长


You are viewing a mobilized version of this site...
View original page here

Mobilized by Mowser Mowser