有朋友問起如何開發一個 WordPress 插件。我自己也不太會寫這方面的東西。就摘一篇官方的教程吧。自己也順便學習一下。

WordPress 插件 允許你通過一種簡單的方式來修改、定義和強化博客的功能。你可以在不修改 WordPress 的核心代碼的情況下,通過插件來直接向 WordPress 中增加功能。

以下是對 WordPress 插件的基本定義:WordPress 插件可以是一個程序,也可以是 PHP 語言編寫的一個或一組函數。它可以通過插件 API 提供的一系列方法和接口,來向 WordPress 網站中增加一些特定的功能或服務,並且讓它們看上去就像是 WordPress 原有的功能一樣。

想要為你的博客添加一些新的或者不一樣的功能?你可以先去 WordPress 插件庫搜索一下,看看是不是有人已經開發了一個符合你要求的 WordPress 插件。如果很不幸——沒有,那麼這篇文章會指導你自己開發一個。

要想讀懂本文中的內容,你需要對 WordPress 的基本功能和 PHP 編程有一定的瞭解。

資源

  • 如果想要了解 WordPress 插件應當如何安裝,以及它們是怎樣工作的,去插件資源集合裏看看,這裏有許多插件開發者的文章和資源,包括如何編寫 WordPress 插件,以及其它特定主題的文章等。
  • 如果想要知道 WordPress 插件是如何編寫的,你可以查看一些插件的源代碼,例如 WordPress 中自帶的 Hello Dolly 插件。
  • 如果你的插件已經寫完了,並且感覺良好的話,你可以閲讀插件提交以及推廣來學習如何把它發佈出去,與他人分享你的勞動成果。

創建插件

這個部分告訴你怎麼把開發插件的理想變為現實。

名字,文件和位置

名字

首先你需要想好這個插件是用來做什麼的,然後你就可以為它起一個獨一無二的名字。如果你不確定這個名字是否被使用過,你可以通過 Google 或者其他的方式來搜索一下。大多數插件開發者為插件起的名字都能很直觀地描述它的功能,例如,一個與天氣有關的插件的名字中就應當包含 「天氣」 兩個字。插件的名字可以由多個字詞組成。

文件

下一步就是根據你插件的名字,創建一個 PHP 主文件。舉個栗子,如果插件的名字叫做 「Fabulous Functionality」,那麼 PHP 主文件的名字就可以是 "functionality.php",當然,還要注意重名的問題。因為用户在安裝你的插件的時候,會默認把你的插件安裝到一個叫 wp-content/plugins/的目錄下,如果兩個插件的文件名衝突了,那就杯具了。

你的插件中至少應當包含一個 PHP 主文件 (當然你也可以把它拆分成多個文件),還可以包含 Javascript 文件、 CSS 文件、圖片文件以及語言文件等。如果你的插件中包含多個文件,你還需要建立一個文件夾,並把插件包含的所有文件放到這個文件夾中,這樣你只要讓其他人把整個文件夾放到 wp-content/plugins/目錄下就可以了。插件文件夾的名稱通常和插件 PHP 文件的名稱相同,例如 PHP 文件的名稱叫做 functionality.php 的話,文件夾的名稱就可以叫做 functionality 。

需要注意的是,由於在 WordPress 中可以配置 wp-content/plugins/目錄的位置,所以你必須使用 plugin_dir_path() 和 plugins_url() 兩個函數來獲取插件的路徑。

查看 http://codex.WordPress.org/Determining_Plugin_and_Content_Directories 以獲取更多信息

  • 在這篇文章之後的部分,如果再提到 「PHP 主文件」 這個概念的話,指的就是插件中最主要的 php 文件,這個文件通常位於 wp-content/plugins/目錄或其子目錄下。

自述文件

如果你想將你的插件發佈到 http://WordPress.org/extend/plugins/, 你必須在插件包中建立一個標準格式的 readme.txt 文件.

你可以訪問 readme.txt 查看如何去格式化自述文件,或者訪問 plugin-readme 來使用文檔自動生成器

需要注意的是,WordPress 是通過自述文件來判斷這個插件是處於 「必要」 還是 「測試」 狀態的。

主頁

為你的插件建立一個主頁會非常有用,你可以在插件的主頁上對插件的功能、安裝方法、使用説明、適用的 WordPress 版本以及插件更新信息等進行介紹。

文件頭

現在開始吧,首先讓我們向 PHP 主文件中加入一些信息

標準插件信息

插件的主文件頂部必須包括一個標準插件信息頭。 WordPress 通過標準信息頭識別插件的存在,並把它加入到控制面板的插件管理頁面,這樣插件才能激活,載入插件,並運行裏面的函數;如果沒有信息頭,插件將無法激活和使用。標準信息插件頭的格式為:

<?php
/*
Plugin Name: 插件名稱
Plugin URI: http://URI_Of_Page_Describing_Plugin_and_Updates
Description: 插件的簡單描述
Version: 插件版本號, 例如: 1.0
Author: 插件作者
Author URI: http://URI_Of_The_Plugin_Author 作者地址
*/
?>

標準信息頭至少要包括插件名稱,這樣 WordPress 才能識別你的插件。其他信息將顯示在控制面板插件管理頁面中。標準插件信息對各行順序沒有要求。

版權信息

通常我們還要在標準信息頭中加入插件的許可證信息。大多數插件使用 GPL 或 GPLCompatibleLicenses 許可。如果使用 GPL 許可,要求插件中包含以下信息:

<?php
/*  Copyright 年份  作者名  (email : 你的郵箱)

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
?>

開始編寫插件

現在是時候讓你的插件做些事情了。這部分內容包括插件開發的一般思路,以及需要完成的工作。

WordPress 插件鈎子

在 WordPress 中,「插件鈎子」 是一個非常重要的概念。許多 WordPress 插件都是通過與插件鈎子相關聯的方式,來完成他們的功能的。插件鈎子的工作原理是:在 WordPress 運行期間,有許多特定的時間點,WordPress 會在這些時間點檢測相應的插件鈎子,如果檢測到有函數與當前的插件鈎子相關聯的話,就會運行這些函數。正是這些函數改變了 WordPress 的默認功能。

例如,當 WordPress 在發表一篇文章之前,會首先檢測一個名為」the_title」 的插件鈎子 (過濾器類型的鈎子),如果此時有任何插件的函數與這個鈎子相關聯的話,那麼文章的標題就會首先被這些函數依次進行處理,最後再把函數處理的結果顯示到屏幕上。所以,如果你的插件想要對文章的標題進行處理的話,就需要將對應的處理函數註冊到名為」the_title」 的過濾器鈎子上。

再舉個例子,在 WordPress 即將生成</HTML> 標籤之前,會檢測一個名為」wp_footer」 的插件鈎子 (動作類型的鈎子),如果此時有插件的函數與這個鈎子相關聯的話,那麼 WordPress 就會先依次執行這些函數,然後再繼續生成</HTML> 標籤。

如果想要了解動作類型鈎子和過濾器鈎子的區別、如何向鈎子上註冊函數,以及 WordPress 在什麼時間點會調用哪些插件鈎子,你可以參閲 Plugin API 。如果您發現了一個想要對其進行處理的時間點,但是 WordPress 並未對這個時間點提供插件鈎子的話,您也可以通過 Reporting Bugs 向我們提出建議,您的建議通常都會被我們採納。

模版標籤

另一個向 WordPress 中加入插件的方式就是建立自定義的模板標籤 Template Tags 。這樣如果有人想要使用你的插件,就可以把這些標籤添加到他們的主題、側邊欄、文章內容以及任何合適的地方。例如,可以為插件定義一個名為 geotag_list_states()的模板標籤函數,該函數可以為側邊欄的文章添加地理位置標籤,當點擊這個標籤時,還可以打開這個地理位置標籤下所有對應的文章。

要定義一個自定義模板標籤,你只需要寫一個 PHP 函數,然後把它通過文檔、插件的主頁或是在 PHP 主文件中聲明的方式告訴插件的使用者就可以了。當你為這個函數編寫文檔的時候,如果還能夠提供一個該函數的使用示例,來告訴用户在主題中應當如何調用這個函數,就再好不過了。

保存插件數據到數據庫

大多數 WordPress 插件都需要獲取管理員或用户輸入的一些信息,並保存在會話中,以便在過濾器函數 (filter) 、動作函數 (action) 和模板函數 (template) 中使用。若需要在下次會話中繼續使用這些信息,就必須將它們保存到 WordPress 數據庫中。

以下是將插件數據保存到數據庫的 4 種方法:

1. 使用 WordPress 的」 選項」 機制 (稍後會有介紹) 。這種方式適合儲存少量靜態的、具有特定名稱的數據——這類數據通常是網站所有者在創建插件時設置的一些初始化參數,並且以後很少會進行改動。

2 、使用文章元數據 (又名自定義域) 。這種方式適合保存與個人文章、頁面或附件相關的數據。若需要了解更多,請參閲 post_meta 函數示例,以及與 add_post_meta() 相關的函數。

3 、使用自定義分類。這種方式適合保存那些需要分門別類存放的數據,如用户信息、評論內容以及用户可編輯的數據等,特別適合於當你想要根據某個類型去查看相關的文章和數據的情況。若需要了解更多,請參閲 Custom Taxonomies 。

4 、創建一個新的,自定義的數據庫表。這種方式適合保存那些與個人文章、頁面或附件無關的,會隨着時間逐漸增長的,並且沒有特定名稱的數據。關於如何使用,你可以閲讀 Creating Tables with Plugins 以獲取更多信息。

WordPress 選項機制

參閲 Creating Options Pages,你將學會如何去創建一個自動保存選項數據的頁面。

WordPress 有一個」 選項」 機制,用於保存、更新以及檢索那些獨立的,具有特定名稱的數據。選項的值可以是字符串、數組,甚至是 PHP 對象 (當然,PHP 對象在保存時必須能夠被序列化或轉換成字符串,檢索的時候也必須能夠被反序列化) 。選項的名稱必須是字符串,且必須是唯一的,這樣才能夠確保它們不會和 WoredPress 或其它插件產生衝突。

通常情況下,你最好能夠對插件選項的數量進行一下精簡。例如,如果你有 10 個不同名稱的選項需要保存到數據庫中,那麼,你就可以考慮將這 10 個數據作為一個數組,並保存到數據庫的同一個選項中。

以下是讓你的插件使用選項機制的主要函數:

add_option($name, $value, $deprecated, $autoload);

創建一個新的選項並保存到數據庫中,若選項已存在,則不進行任何操作。

$name:必要參數 (string) 。要創建的選項的名稱。

$value:可選參數 (string) 。要創建的選項的值。默認值為空字符串。

$deprecated:可選參數 (string) 。該選項是否已經過期。若需要讓後面的 $autoload 參數生效,則該參數必須傳入空字符串或 null 。

$autoload:可選參數 (enum: 『yes』 or 『no』) 。是否自動加載該選項。若設置為 『yes』,則該選項會被 get_alloptions 函數自動檢索到。默認值為 『yes』 。

get_option($option);

從數據庫中獲取指定選項的值。

$option:必要參數 (string) 。選項的名稱。你可以在 Option Reference 中找到與 WordPress 一同安裝的默認選項列表。

update_option($option_name, $newvalue);

更新數據庫中的選項值,若選項不存在,則創建該選項。 (注意:如果你用不到 $deprecated$autoload 參數的話,那麼大可不必使用 add_option 函數) 。

$option_name:必要參數 (string) 。要更新/創建的選項名稱。

$newvalue:必要參數 (string|array|object) 。要更新/創建的選項的值。

管理面板

假定你的插件有一些選項 (option) 存儲於 WordPress 的數據庫中 (參看上一節), 你可能會想要一個主控面板來允許你的插件用户查看和編輯選項值。實現這一目標的方法闡述於 Adding Administration Menus 。

插件國際化

在你完成了你的插件的編寫工作之後,另一個需要考慮的問題 (假設你準備跟大家分享你的插件的話) 就是將其國際化。國際化就是將你的軟件設置成能夠本地化的過程;本地化是將軟件中顯示的語言翻譯成其他語言的過程。 WordPress 正在被全球的人們使用,所以全球化和本地化是他內在的特性,這其中就包括了插件的本地化。

我們十分希望你能夠將你的插件國際化,這樣其他國家的用户就可以在自己的本地使用它了。我們有一個關於國際化的綜合説明在 I18n for WordPress Developers,這其中就包括了一個描述插件國際化的部分。

更新你的插件

這個部分描述必要的步驟來更新你在 http://WordPress.org/extend/plugins 上的插件, 還包括在 WordPress.org 中使用 Subversion(SVN) 的細節。

假設你已經提交了你的插件到 WordPress 插件存儲庫。隨着時間的推移, 你可能會發現需要並希望將添加新的功能到您的插件或修正錯誤。你常常想要完成這些改變並提交它們到你的插件的主幹。變化將是公開可見的, 但只有專業人員通過 SVN 才能查看你的插件,其他用户通過網站或他們的 WordPress 插件管理下載的將不會改變。

當你準備發佈一個新版本的插件時:

  • 確保一切都被提交併且新版本可以正常工作。注意測試所有你的插件所支持的 WordPress 版本。也不只是測試新特性,確保你沒有不小心破壞一些老的功能插件。
  • 更新主 PHP 文件中頭註釋的版本號 (在主文件夾) 。
  • 更新 readme.txt 文件中的』Stable tag』 的版本號 (在主文件夾) 。
  • 在 readme.txt 文件中添加一個新的部分——「更新日誌 (changelog)」, 簡要描述相比於最後一個版本的變化。它將被列在插件頁中。
  • 提交這些更改。
  • 創建一個新的 SVN 標籤作為主幹的副本, 參見這裏。

給系統幾分鐘去工作, 然後檢查 WordPress.org 插件頁面和 WordPress 上安裝你的插件的頁面, 看看一切是否正確更新和是否在你安裝的 WordPress 中顯示了插件更新 (更新檢查可能會被緩存, 這可能需要一些時間, 試着訪問 「可用更新」 的頁面在你安裝的 WordPress 中) 。

故障排除:

  • 在 WordPress.org 上的插件頁面仍然列出了舊版本。你是否更新主文件夾中的』stable tag』?只是創建一個標籤, 更新 readme.txt 在標籤文件夾中是不夠的!
  • 插件頁面提供了一個新版本的 zip 文件,但按鈕仍然列出了舊版本號並且在你的安裝 WordPress 中並沒有更新通知。你是否記得更新 「版本 (Version)」 的註釋在主 PHP 文件中?
  • 對於其他問題請參考 Ocodeo 的關於常見問題的頁面:The Plugins directory and readme.txt files

插件開發建議

最後這個部分是關於開發插件的一些建議。

  • WordPress 插件的代碼應該遵循 WordPress Coding Standards. 另外請同時參考 Inline Documentation 。
  • 你的插件中所有函數的名稱都應該與現存的 WordPress Core 函數,其他插件或主題的任何名稱不同。基於這個原因,我們建議你在你的插件的所有函數的名稱之前加上一個你自己選擇的前綴,或者把你的插件的函數都寫在一個類裏面 (當然這個類的名字也必須是唯一的) 。
  • 請不要把 WordPress 數據庫表格前綴 (通常是 「wp_」) 直接寫在你的插件裏,請使用 $wpdb->prefix 。
  • 雖然數據庫的讀取相對便宜,但它的寫入是相當昂貴的。數據庫十分擅長獲取信息並呈現給用户,而且這些操作 (通常) 是非常迅速的。然而對數據庫進行改動就是一個非常複雜的過程了,而且需要使用更長的計算時間。因此,請儘量減少你對數據庫進行寫入的次數。在你編寫程序的時候就做好所有的準備,這樣就可以只在必須的時候再進行寫入了。
  • 在數據庫裏只 SELECT 你需要的東西。儘管數據庫的讀取十分便捷,我們依然推薦你值查找真正需要的數據,來儘量減少數據庫的負載。例如,如果你只想獲得表格的行數,不要使用 SELECT * FROM, 因為這樣的話每一行中的所有數據都會被讀出,導致內存的浪費。同樣的,如果在插件中你只想獲得 post_id 和 post_author,請只 SELECT 這兩項來減少數據庫的負載。記住:在某一個操作的同時可能有其他上百個進程需要使用數據庫,而數據庫和服務器都必須同時滿足所有這些進程的需求。學習怎樣儘量減少你的插件對數據庫的使用可以避免對這些資源的濫用。
  • 不要讓你的 PHP 出錯。在你的 wp_config.php 文件中添加 define('WP_DEBUG',true);,對你的所有函數進行測試來確定是否有任何的錯誤或者警告。有多少,就修復多少,直到再也不出現為止。

原文:http://codex.WordPress.org/Writing_a_Plugin