本欄目下相關鏈接
插件設計
您在開始論壇插件的設計之前，有必要瞭解一下我們所推薦的插件設計方式，更好的規範性和兼容性，將使得您設計的插件受到更多使用者的歡迎，對於程序員而言，也有助於形成良好的編碼習慣，實現自身能力的提升。如果您有意編寫 Discuz! 論壇插件，請按照先後順序仔細閱讀本文檔。
準備工作
插件實現流程 開始編寫論壇插件，您應當首先對插件實現的流程有一個大致的瞭解，以下是我們推薦的插件編寫流程： 熟練使用 Discuz! 論壇系統後，對希望完善或補充的個性化功能進行評估，進而提出插件的功能需求； 對插件做一個概括性的設計，例如：需要使用什麼菜單、什麼參數，配置哪些選項、數據結構如何設計、前後台實現哪些功能等等； 閱讀本文檔並在系統設置中實際體驗 Discuz! 插件接口所實現的功用，例如：您的插件應當如何設計才能良好的掛接到論壇系統中來；插件接口能夠實現哪些功能、不能實現哪些功能，插件為此而需要做的優化、改造和取捨； 編寫相應程序代碼和模板語句，實現所需的功能並進行代碼測試、兼容性測試和代碼改進； 如果需要公開您的插件，可以用插件導出的方式，將插件配置信息導出到一個文本文件中，連同相應的程序和模板文件一同打包。同時，編寫一個適合新手的插件的說明書也是必不可少的，其中包括：插件適用的 Discuz! 版本、功能概述、兼容性聲明、安裝方法、使用方法、卸載方法等等； 將插件提供給他人，或自己使用，根據使用者反饋，對插件進行完善。插件實現流程至此結束。 文件命名規範 Discuz! 按照如下的規範對程序和模板進行命名，請在設計插件時盡量遵循此命名規範： 可以直接通過瀏覽器訪問的普通程序文件，以 .php 後綴命名。 被普通程序文件引用的程序文件，以 .inc.php 後綴命名。 被普通程序文件，或引用程序文件引用的函數庫或類庫，以 .func.php(函數庫) 或 .class.php(類庫) 後綴命名。 模板文件，以 .htm 後綴命名，模板文件只存在於 ./templates 目錄中。 模板語言包文件，以 .lang.php 後綴命名，語言包文件只存放於 ./templates 目錄中，與模板文件同級目錄。 被編譯後的模板文件，以 .tpl.php 後綴命名，前面的數字是模板套系的 ID，下劃線後面的是模板原名，編譯模板文件只存在於 ./forumdata/templates 目錄中。 動態緩存文件，存放於 ./forumdata/cache 目錄中，依據不同的功用進行獨立的命名。 使用後台數據備份功能生成的備份文件，通常以 .sql 為後綴，存放於 ./forumdata/ 目錄中。 有些目錄中存在內容為空白的 index.htm 文件，此類文件是為了避免 Web 服務器打開 Directory Index 時可能產生的安全問題。 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」為例進行說明。 在插件管理中添加插件後，僅僅是增加了一條插件記錄，後面還需要很多相關的設計和設置。在列表中選擇插件的「詳情」進入插件的詳細設置。插件設置分為三個部分： 插件基本設置： 設置插件的基本參數，配置項目右邊括號中的內容，為此設置對應的參數名稱，調用方法將在後面的《參數讀取與緩存控制》中詳細說明。 插件模塊和自定義菜單： 插件接口默認提供四種可選的模塊方式： 直接鏈接（前台菜單）：可在前台右上角加入一個菜單項，可自主指派菜單鏈接的 URL。注意：由於引用外部程序，因此即便設置了模塊的使用等級，您的程序如需權限判斷，仍需要引用 common.inc.php 和插件相關的緩存文件（將在後面的《參數讀取與緩存控制》中詳細說明），並自行判斷使用等級是否合法； 前台調用（前台菜單）：與直接鏈接類似，但其調用的是插件的一個模塊，模塊文件名指派為「./plugins/插件目錄/插件模塊名.inc.php」，由 plugin.php 調用此模塊，調用 URL 將在後面的《編寫插件的原則與注意事項》中詳細說明； 後台調用（後台菜單）：可在後台插件設置中為此插件增添一個管理模塊，模塊文件名指派為「./plugins/插件目錄/插件模塊名.inc.php」，由 admincp.php 調用此模塊，調用 URL 將在後面的《編寫插件的原則與注意事項》中詳細說明； 包含運行（無菜單）：可設置一個在論壇所有頁面均包含運行的腳本，此腳本在 ./include/common.inc.php 中加載，腳本文件名指派為「./plugins/插件目錄/插件模塊名.inc.php」。請注意，為了不導致錯誤的插件影響論壇運行，在 common.inc.php 加載此模塊時，屏蔽了錯誤信息，因此請務必仔細檢查是否存在語法錯誤，任何微小的語法錯誤都將不被提示出來，並且導致此模塊不被正常加載。如果您配置了不正確的包含腳本而導致論壇系統設置無法使用，刪除服務器上相應的腳本文件即可解決。 您可以為每個模塊設置不同的使用等級，例如設置為「超級版主」，則超級版主及更高的管理者（例如論壇管理員）可以使用此模塊。 插件鉤子設置： 插件鉤子能夠將插件代碼埋藏在程序中的任意位置，從而實現更加靈活的插件功能，最大限度的減少對原有程序代碼的修改。 論壇版本升級後，只需將相應鉤子重新埋入相應程序中，原有插件即可繼續使用。 關於插件鉤子的具體設計方法請見下面的《插件鉤子的設計》。 插件變量配置： 插件接口中提供了一個通用的插件配置管理程序，在大多數情況下可實現插件的參數配置，省卻了插件開發者自行編寫後台管理模塊（即上面提到的「後台調用（後台菜單）」模塊）的麻煩。通常情況下，應優先使用通用插件配置管理程序來實現插件的參數配置，只有在通用程序確實無法實現時，才自行編寫後台管理模塊。輸入配置名稱和配置變量名、選擇合適的配置類型後，即可為此插件增加一個配置變量，點「詳情」可以編輯此配置變量的更多信息。為了方便插件程序調用使用者配置好的參數，配置變量同樣被存放在了緩存文件中，讀取方法將在後面的《參數讀取與緩存控制》中詳細說明。 注意：您只有在插件管理中將插件設置為「可用」，以上設置才能生效。
參數讀取與緩存控制
編寫插件程序時，可能需要讀取一些插件的信息，如果插件需要使用者進行配置，還需要讀取使用者設置的參數值。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']);
- - 設計範例 此處我們為您提供一個使用鉤子技術的插件範例，完成功能十分簡單，旨在使您直觀的瞭解鉤子的使用。此範例實現了當遊客訪問論壇首頁時，強制用戶登錄的功能。 進入系統設置中的插件管理，添加一個名稱和惟一標識符均為 demo 的插件； 編輯插件 demo 詳情，找到「插件鉤子設置」，添加一個名為 index_force_loggedin 的鉤子，然後提交； 編輯鉤子 index_force_loggedin，按如下內容填寫設置： 鉤子描述：當遊客訪問論壇首頁的時候，程序會彈出提示框，並自動跳轉到登陸頁面； PHP代碼：
        	if(!$discuz_uid) {
        		showmessage('請您登陸後訪問本站，現在將轉入登錄頁面。', 'logging.php?action=login');
        	}
- - 提交後，回到此插件的設置頁面。將鉤子 index_force_loggedin 設置為可用； 點擊左側導航，進入插件管理，將插件 demo 設置為可用； 編輯論壇程序 index.php 安放鉤子，方法如下： 查找代碼：
        	$discuz_action = 1;
  - 在上述代碼下放添加代碼：
        	eval($hooks['demo_index_alter']);
保存文件後將文件上傳到服務器； 至此，一個簡單的使用鉤子實現的插件已經徹底完成。您可以退出登陸並訪問論壇首頁，測試一下插件的效果。 Discuz! 插件的鉤子技術，為廣大的插件開發者提供了一個更加靈活的插件設計機制。當 Discuz! 升級後，用戶只需重新將鉤子調用代碼安放到程序中原來的位置，就幾乎可以繼續使用原來已安裝的插件，降低了對於程序修改的幅度和插件安裝的難度，更加有利於插件程序的規範、管理、維護、相互交流。因此我們強烈建議插件開發者能夠深入研究個應用這一機制，創作出越來越多的優秀插件。
意見反饋
插件接口是 Discuz! 開發組為了方便插件設計、安裝和使用而專門開發，雖然經過長期的優化和改進，可能仍然會有不夠合理或不夠完善的地方，歡迎各位插件程序員在使用此接口的過程中，為我們提出意見和建議，感謝您的支持。