本欄目下相關鏈接 |
|
插件設計 |
您在開始論壇插件的設計之前,有必要瞭解一下我們所推薦的插件設計方式,更好的規範性和兼容性,將使得您設計的插件受到更多使用者的歡迎,對於程序員而言,也有助於形成良好的編碼習慣,實現自身能力的提升。如果您有意編寫 Discuz! 論壇插件,請按照先後順序仔細閱讀本文檔。
|
準備工作 |
插件實現流程 文件命名規範 common.inc.php 模塊功能白皮書
./include/common.inc.php 是 Discuz! 的通用初始化模塊程序,其幾乎被所有的外部代碼所引用,在您開始插件設計之前,可以先對該模塊的大致功能做一定的瞭解。common.inc.php 主要完成了以下任務:
- 對不同 PHP 及操作系統環境做了判斷和兼容性處理,使得 Discuz! 可以運行於各種不同配置的服務器環境下。
- 初始化常量 IN_DISCUZ 為 TRUE,用於 include 或 require 後續程序的判斷,避免其他程序被非法引用。
- 讀取論壇所在絕對路徑,存放於常量 DISCUZ_ROOT 中。
- 加載所需的基本函數庫 include/global.func.php。
- 通過 config.inc.php 中提供的數據庫賬號信息,建立數據庫連接。Discuz!支持數據表的前綴,如需獲得表的全名,可使用」{$tablepre}tablename」
或 $tablepre.』tablename』的方式。
- 判斷用戶是否登錄,如登錄標記 $discuz_uid 為非 0,同時將 $discuz_user(加了 slash 的用戶名,可用於不加修改的插入數據庫)、
$discuz_userss(原始的用戶名,可用於頁面顯示)、$discuz_pw(用戶密碼的MD5串)、$discuz_secques(登錄提示問題的加密串)等相應用戶信息賦值。
- 判斷用戶管理權限,將管理權限標記 $adminid 為 -1~3 中間的值。-1 代表為特殊用戶組用戶。0 代表普通用戶;1 代表論壇管理員;2 代表超級版主;3 代表論壇版主。
將用戶權限按照其所在的主用戶組 ID 標記為 $groupid,相關權限從該 $groupid 所對應的系統緩存中讀出(./forumdata/cache/usergroup_$groupid.php)。
將用戶擴展權限按照其擴展用戶組 ID 標記為 $extgroupids,中間以 \t(tab) 分隔,格式為「$groupid1\t$groupid2...」,擴展用戶組用於確定用戶的擴展瀏覽權限,例如能否訪問某些有特殊權限設定的論壇等。
- 讀入系統設置中的各種變量,並根據 Cache 模塊的設定,根據當前被調用的程序文件名(如 index.php,forumdisplay.php 等等)讀入
相應的緩存代碼。緩存代碼被存放於 ./forumdata/cache/ 中。除了對應當前程序的緩存,可能還會加載一些通用的緩存數據,例如整個論壇
的設置(./forumdata/cache/cache_settings.php)、界面風格(./forumdata/cache/style_x.php)、當前用戶的用戶組(./forumdata/cache/usergroup_x.php)、
管理組權限(./forumdata/cache/adminusergroup_x.php)等。
- 緩存數據的格式,大多是存放在 $_DCACHE['cachename'] 數組中,有些常用的參數,如系統設置中的參數、風格界面等,通常還被進行了
展開操作(extract)或使用常量進行賦值。
- 用戶如果處在登錄狀態,會自動讀出 members 表相關用戶的參數值,用戶的個性設置參數:如時差、時間格式、界面風格等等,會根據實際
情況覆蓋系統默認值,因此在後續程序通常不用再做判斷。
- 如果程序提交的 URL 中包含 tid=x 或 fid=x,common.inc.php 模塊會自動讀出其所對應的論壇記錄及包括 access masks、版主設定等相應
權限,記錄在 $forum 變量中。後續程序只要通過URL將tid或fid傳遞過來,便可通過 $forum 數組的存在性或相關參數來對論壇權限進行判斷,
不需要再讀 forums 表的資料。
|
插件接口概述 |
使用管理員賬號登錄 Discuz! 系統設置,在左側菜單將可以看到「插件設置」和「插件管理」兩個選項,使用超級版主或版主賬號登錄,將只出現「插件設置」一個選項。「插件管理」是控制插件打開與否、設計插件模塊、菜單、參數和使用權限的地方,插件開發者可以依照設計意圖,在此進行插件的初步設置,這裡同時也提供插件導入和插件開關的功能,用於導入他人設計的插件和對插件的可用狀態進行變更。「插件設置」是對已經安裝的插件進行設置的地方,供使用者對插件參數進行調整以實現不同的插件功能。即前者主要面向開發者,後者主要面向使用者。
開始編寫一個新插件,請首先在插件管理中,輸入新插件的名稱和惟一標識符。名稱用於表明此插件的用途,例如設置為「虛擬銀行插件」。惟一標識符用於在後續的插件模塊中調用本插件,不可與現有插件重複,命名規則限制與 PHP 變量命名相同,雖然初次設置後仍可改動,但強烈建議一次性將此配置設置好,否則可能涉及到很多代碼方面的變更,增加編碼的麻煩。請注意:惟一標識符請不要設置的過短,或使用有可能與其他插件重複的命名,例如製作此插件的公司叫做 Comsenz Inc.,插件名稱是「虛擬銀行插件」,惟一標識符可設置為「comsenz_virtual_bank」,後面將以「虛擬銀行插件」和「comsenz_virtual_bank」為例進行說明。
在插件管理中添加插件後,僅僅是增加了一條插件記錄,後面還需要很多相關的設計和設置。在列表中選擇插件的「詳情」進入插件的詳細設置。插件設置分為三個部分:
|
參數讀取與緩存控制 |
編寫插件程序時,可能需要讀取一些插件的信息,如果插件需要使用者進行配置,還需要讀取使用者設置的參數值。Discuz! 允許插件程序使用數據庫讀取和緩存讀取這兩種方法獲取插件信息和參數。Discuz! 的插件接口已經對插件信息進行了合理的緩存,使用緩存讀取的方式,將比數據庫讀取速度更快,消耗的資源更是幾乎可以忽略不計。緩存讀取唯一的局限是需要插件使用插件接口提供的通用後台管理程序。如果使用自定義後台模塊的方式,需要後台模塊將參數存放到 pluginvars 數據表中,才能被系統正常緩存。我們強烈推薦您通過緩存讀取插件信息和配置數據。
插件數據結構
插件數據使用兩個數據表存放,分別是 plugins 和 pluginvars。前者用於存放插件信息:安裝了多少個插件,就有多少條記錄;後者用於存放插件的配置參數和配置值:所有已安裝的插件總共有多少個配置項目,就有多少條記錄。下面的表格列出了這兩個表的主要字段及其用途說明。
plugins 表:
pluginid 插件的惟一 ID,自動遞增
available 插件是否可用,1=是,0=否
adminid 使用系統設置中插件接口自帶的插件參數設置程序所需的最低權限等級要求,1=管理員,2=超級版主,3=版主
name 插件名稱
identifier 插件惟一標識符
description 插件簡介
datatables 插件數據表,不包含前綴,多個表使用半角逗號「,」分隔
directory 插件所在目錄,例如設置為 comsenz_bank,則對應論壇目錄的位置為 ./plugins/comsenz_bank/
copyright 插件版權信息
modules 插件模塊信息,數組格式,使用 serialize() 序列化後存放
|
pluginvars 表:
pluginvarid 插件配置的惟一 ID,自動地增
pluginid 本項配置所隸屬的插件 ID
displayorder 本項配置的顯示順序,數值低的排在前面
title 插件配置的名稱
description 插件配置的簡介
variable 插件配置的變量名
type 插件配置的類型
value 插件配置的值
extra 當本項配置為「選擇(select)」時,可選的取值範圍
|
如果您使用自行編寫的插件後台管理模塊進行插件參數配置,請盡量將配置項目按照 pluginid 的對應關係,將參數存儲於 pluginvars 表中,這樣系統就可以自動將您增加的配置參數緩存起來,以供插件程序進行調用。
插件參數讀取
瞭解了 Discuz! 插件存儲的數據結構後,您可以在插件程序中根據需要選擇合適的數據讀取方式。由於數據庫讀取方式可以由數據結構推斷而來,因此這裡只介紹緩存讀取的方式,這種方式是我們強烈推薦的插件數據讀取方式。
在管理者配置好插件信息,或用戶進行插件的參數設置之後,系統將根據插件設置的惟一標識符,自動生成一個插件數據的緩存文件,例如惟一標識符為 comsenz_virtual_bank,則緩存文件位於 ./forumdata/cache/plugin_comsenz_virtual_bank.php,您可以打開此文件查看其中的數據內容和格式。緩存採用數組的方式進行存儲,引用此文件即可將所需的插件參數一次性賦值。
其中,$_DPLUGIN['comsenz_virtual_bank'] 這個數組下標,為插件的惟一標識符,所有插件緩存數據,一經被引用,就會賦值到 $_DPLUGIN 這個多維數組中。modules 描述了這個插件的模塊信息,其中 type 為 1~4 的整數值,從小到大依次為「直接鏈接(前台菜單)」、「前台調用(前台菜單)」、「後台調用(後台菜單)」、「包含運行(無菜單)」;vars 描述了這個插件的配置變量,前面為變量名,後面為使用者賦予這個變量的值。
|
編寫插件的原則與注意事項 |
請在您動手編寫插件之前,還需要仔細的閱讀以下原則,遵循這些原則,將有效的避免可能發生的問題:
- 所有與插件的程序,包括其全部的前後台程序,請全部放入 ./plugins 目錄中,同時在插件的安裝說明中指出,插件的文件需要複製到哪些目錄。為了避免與其他插件衝突,請盡量建立 ./plugins 下的子目錄,並將插件程序放置於子目錄下,這樣您編寫的插件將獲得更好的兼容性。
- 如果您的插件包含「前台調用(前台菜單)」模塊,該模塊將統一用 plugin.php?identifier=xxx&module=yyy 的方式調用,請在相應鏈接、表單中使用此方式。其中 xxx 為插件的惟一標識符,yyy 為模塊名稱。前台插件外殼程序 plugin.php 已經加載了通用初始化模塊(./include/common.inc.php),不需再次引用。
- 如果您的插件包含「後台調用(後台菜單)」模塊,該模塊將統一用 admincp.php?action=plugins&identifier=xxx&mod=yyy 的方式調用,請在相應鏈接、表單中使用此方式。其中 xxx 和 yyy 的定義與「前台調用(前台菜單)」模塊中的相同。系統還允許用 admincp.php?action=plugins&edit=$edit&mod=$mod 的方式來生成鏈接和表單地址,$edit 和 $mod 變量已經被插件後台管理接口賦值,因此將這兩個變量值帶入 URL 中也是被支持的。由於後台模塊是被 admincp.php 調用,因此已加載了通用初始化模塊(./include/common.inc.php)並進行了後台管理人員權限驗證,因此模塊程序中可直接寫功能代碼,不需再進行驗證。
- 請勿繞過插件的前後台外殼(plugin.php 和 admincp.php)而以直接調用某程序的方式編寫插件,因為這樣既導致了用戶使用不便,代碼冗余和不規範,同時又產生了因驗證程序考慮不周到而帶來的安全隱患。您可以在任何地方,包括鏈接、表單等處方便的使用上述 URL 地址對插件模塊進行調用。
- 所有與插件有關的程序,包括全部的前後台程序,因全部使用外殼調用,請務必在第一行加入
if(!defined('IN_DISCUZ')) {
exit('Access Denied');
}
|
以免其被 URL 直接請求調用,產生安全問題。
- 一般情況下,您發佈插件請使用插件導出的功能,以方便使用者一次性導入插件的配置數據,極特殊的情況下,也可以分步驟告知使用者如何進行插件配置管理和安裝此插件。
- 如果功能獨立,請盡量使用單獨程序的方式編寫插件(即外掛型插件),而盡量少的對論壇本身代碼進行修改,這將為使用者今後的升級帶來很大方便。
- 您可以修改 Discuz! 本身的數據結構,但更推薦在不很影響效率的前提下將插件數據用另外的數據表存儲,因為不能排除您增加的字段或索引和今後版本 Discuz! 核心數據字段重名的可能。在任何情況下,請不要刪除 Discuz! 標準版本數據結構中已有的字段或索引。
- 請在插件說明書中對插件做以詳盡的描述,例如增加了哪些字段、哪些表,修改了或新增了哪些程序,版本兼容性,後續支持的提供方式(例如不提供支持,或以什麼樣的方式提供)。如果方便,請盡可能提供插件的卸載方法,例如去除哪些字段、刪除哪些新增的程序、將哪些被插件修改的程序恢復原狀等等,使用者會感激您為此付出的辛勤勞動,甚至願意支付相應的費用支持您未來的發展。
- 如果插件使用另外的數據表存儲,請在插件管理中準確的設置插件所使用的數據表名稱(不包含前綴),這樣用戶在備份數據的時候,能夠把插件數據一同備份。
- Discuz! 自 4.0.0 版本起,內置了 8 種自定義積分,存儲於 members 表中的 extcredits1 至 extcredits8 字段中,類型為有符號整數,您可以在引用 common.inc.php 後,在 $extcredits 或 $_DCACHE['settings']['extcredits'] 中讀取 8 種積分的啟用信息(詳情請參考 ./forumdata/cache/cache_settings.php)。插件程序中如需更新用戶積分,可直接 UPDATE 相應的積分字段,無需其他操作。
|
插件鉤子的設計 |
插件鉤子的設計,需要您具有一定編程基礎,比較瞭解 Discuz! 論壇程序的結構,並能夠使用 PHP 語言撰寫代碼。對於普通用戶,可以略過以下內容。 插件鉤子(以下簡稱「鉤子」)屬於插件的一部分,因此在設計鉤子之前應當首先進入後台——插件管理,新增插件或者編輯一個現有的插件,即可看到相關設置。
鉤子的添加
- 鉤子名稱:在一個插件內,鉤子的名稱是唯一的,不可重複。名稱可以由英文字母、數字和「_」組成,不支持中文,最長255個字符。為了便於理解和記憶鉤子的作用, 名稱應當盡量簡潔清晰,能夠表述一定的含義。注意:鉤子名稱對字母大小敏感,例如:Index_start 和 index_start 將視為兩個不同的鉤子。
- 鉤子描述:對鉤子的詳細說明,如功能介紹、調用方法、使用方法等。
- PHP代碼:這裡是鉤子的核心內容,也是一段PHP代碼,需要您自行設計,完成鉤子需要處理的數據或者需要執行的操作。
- 可用:每個插件允許有多個鉤子,您可以自由選擇關閉或者開啟某個鉤子。
鉤子的刪除
鉤子的編輯與升級
- 編輯:插件設計階段,您可能需要隨時編輯鉤子,每次更改,系統會自動更新緩存文件,您可以立即看到更改的效果。如果是更改鉤子名稱,那麼您可能需要調整鉤子放置的程序,修改鉤子調用的名稱。
- 升級:論壇程序進行升級之前,您應當使用插件的導出功能,導出插件備份。論壇升級並正常運行後,再導入插件備份,修改相關程序,重新安放鉤子。
鉤子的放置與調用
鉤子設計完成以後,您需要在相應的程序中安放鉤子,不同鉤子由於作用的不同,放置的位置也是不同的。 安放鉤子,您僅僅需要將鉤子的調用代碼放入即可。調用代碼格式如下:
eval($hooks['插件唯一標識符(identifier)_鉤子名稱']);
|
例如:調用 插件demo 的鉤子 testhook, 我們需要在程序中適當的地方加入下面的代碼
eval($hooks['demo_testhook']);
|
設計範例 Discuz! 插件的鉤子技術,為廣大的插件開發者提供了一個更加靈活的插件設計機制。當 Discuz! 升級後,用戶只需重新將鉤子調用代碼安放到程序中原來的位置,就幾乎可以繼續使用原來已安裝的插件,降低了對於程序修改的幅度和插件安裝的難度,更加有利於插件程序的規範、管理、維護、相互交流。因此我們強烈建議插件開發者能夠深入研究個應用這一機制,創作出越來越多的優秀插件。
|
意見反饋 |
插件接口是 Discuz! 開發組為了方便插件設計、安裝和使用而專門開發,雖然經過長期的優化和改進,可能仍然會有不夠合理或不夠完善的地方,歡迎各位插件程序員在使用此接口的過程中,為我們提出意見和建議,感謝您的支持。
|