phpwind 9插件開發(fā)速成教程(含實(shí)例和源碼)

2013-01-15 14:31:46來源:phpwind作者:

這篇文章被收錄與phpwind開發(fā)文檔之中,教主同學(xué)寫的一篇phpwind9插件開發(fā)速成心法。
 

這篇文章被收錄與phpwind開發(fā)文檔之中,教主同學(xué)寫的一篇phpwind9插件開發(fā)速成心法。
 

什么是插件

插件是增加網(wǎng)站功能,實(shí)現(xiàn)差異化運(yùn)營(yíng)的重要手段
通常所說的插件,其實(shí)都是泛指插件與擴(kuò)展,兩者區(qū)別是:

  1. 插件 具有獨(dú)立訪問地址,功能可以自成體系的功能模塊
  2. 擴(kuò)展 通過鉤子系統(tǒng)注入到系統(tǒng)中以達(dá)到接管或改進(jìn)原有系統(tǒng)的功能模塊

有一個(gè)比較容易混淆的概念是,phpwind9.0的導(dǎo)航上有一個(gè)應(yīng)用中心 這里所謂的應(yīng)用,其實(shí)都是插件(插件也叫應(yīng)用)

插件的原理

  1. 插件 是通過框架分發(fā)器的模式匹配功能來實(shí)現(xiàn)的,所以開發(fā)一個(gè)插件本質(zhì)上跟開發(fā)應(yīng)用是一樣的
  2. 擴(kuò)展 通過鉤子系統(tǒng)注入到系統(tǒng)中的功能模塊,依賴系統(tǒng)的功能運(yùn)行而運(yùn)行

準(zhǔn)備工作

注冊(cè)成為開發(fā)者

  1. 成為開發(fā)者,可以使你開發(fā)的插件為所有phpwind站點(diǎn)使用
  2. 可以讓你的插件成為唯一,以防與其他開發(fā)者命名沖突
  3. 當(dāng)然如果你愿意,這可以為你帶來一筆收入
  4. 開發(fā)者注冊(cè)地址

Zhanghao.JPG 身份認(rèn)證.jpg

了解開發(fā)助手

  • 進(jìn)入后臺(tái)->站點(diǎn)設(shè)置->全局參數(shù)-> DEBUG 模式運(yùn)行站點(diǎn),輸入520(或1314),開啟開發(fā)者模式
  • 進(jìn)入后臺(tái)->云平臺(tái)->應(yīng)用管理->開發(fā)助手 按照提示輸入,建立一個(gè)插件

App zhushou.jpg

  • 在src/extensions/目錄下,能找到你剛生成的插件文件夾
  • 如果DEBUG模式為1314,還可以在前臺(tái)頁(yè)面上看到已埋的鉤子標(biāo)識(shí)

App gouzi.jpg

開發(fā)者版本

  1. 為了更好地與開發(fā)者保持交流,我們實(shí)時(shí)公布研發(fā)版本的代碼動(dòng)態(tài),此上面的更新將全部放入下個(gè)版本
  2. 下載地址 https://github.com/phpwind/nextwind

插件開發(fā)規(guī)范

由于系統(tǒng)可能同時(shí)存在多個(gè)插件,尤其是云平臺(tái)開通之后,插件安裝極其便利,為了避免插件之間的沖突,定義如下規(guī)范:

插件唯一標(biāo)識(shí)符

  1. 標(biāo)識(shí)符由字符、數(shù)字組成,不能包含_
  2. 標(biāo)識(shí)符需能明確表達(dá)插件的含義,否則無(wú)法通過云平臺(tái)驗(yàn)證(不提交到云平臺(tái)的插件略過)
  3. 標(biāo)識(shí)符可以到云平臺(tái)申請(qǐng)
  4. 比如當(dāng)前申請(qǐng)到的唯一標(biāo)識(shí)符為sign,以下皆以此為例

數(shù)據(jù)庫(kù)命名規(guī)范

  1. 表命名 統(tǒng)一添加表前綴,表前綴為pw_app_sign_(pw_前綴是站長(zhǎng)安裝時(shí)選擇的,可能各個(gè)站不一樣)
  2. 擴(kuò)展字段 插件不建議在原生數(shù)據(jù)表上增加字段,但并不限制。所有增加的字段必須帶上前綴app_sign_

類命名(文件名)規(guī)范

  1. 所有類命名(Controller除外)必須帶上前綴 App_Sign_,駝峰形式+下劃線_

插件配置規(guī)范

為防止插件之間配置項(xiàng)命名沖突,我們作如下約定:
  1. 獨(dú)立配置域 配置域命名規(guī)則為 app_sign
  2. 公共配置域 對(duì)于某些配置到公共配置域的配置項(xiàng),配置項(xiàng)加前綴 app.sign.

鉤子鍵名(alias)命名規(guī)范

  1. alias命名加前綴 app_sign

后臺(tái)菜單項(xiàng)鍵名命名規(guī)范

  1. 鍵名命名加前綴 app_sign

用戶組權(quán)限鍵名命名規(guī)范

  1. 鍵名命名加前綴 app_sign

開發(fā)演示

選取一個(gè)題材

我們選取互聯(lián)網(wǎng)上SNS社區(qū)比較流行的一款增加用戶粘性的互動(dòng)游戲“動(dòng)他一下”作為本次的開發(fā)示例。
別忘了,上開發(fā)者平臺(tái)驗(yàn)證一下,是否已經(jīng)有人開發(fā)過了哦

這個(gè)插件做些什么

  1. 應(yīng)該有一個(gè)獨(dú)立頁(yè)面,列出我的所有好友,我可以輕松的動(dòng)“他們”一下
  2. 訪問別人空間的時(shí)候,我可以動(dòng)“他們”一下
  3. 看別人帖子的時(shí)候,我也要?jiǎng)?ldquo;他們”一下;
  4. 哦,別忘了,還需要一個(gè)后臺(tái)設(shè)置

Dongta.jpg

創(chuàng)建應(yīng)用

  • 進(jìn)入后臺(tái)->云平臺(tái)->應(yīng)用管理->開發(fā)助手
  • 按照提示,填寫相關(guān)信息
  • 這里有三個(gè)選擇需要注意一下
  1. 選擇應(yīng)用額外安裝服務(wù) 這個(gè)有三個(gè)菜單可以選擇,我們只需要在主導(dǎo)航中添加應(yīng)用,故勾選nav_main
  2. 是否需要管理后臺(tái)界面 選需要,會(huì)幫我們自動(dòng)生成一個(gè)菜單項(xiàng)和演示頁(yè)面
  3. 是否生成數(shù)據(jù)服務(wù)類 本應(yīng)用要用到數(shù)據(jù)庫(kù),所以選需要
  • 提交,馬上創(chuàng)建
  • 在應(yīng)用管理,已安裝菜單下,就能發(fā)現(xiàn)剛才創(chuàng)建的“動(dòng)他一下”應(yīng)用了
  • 嗯,logo不對(duì),找到 src/applications/extensions/dongta/res/images 替換一張logo.jpg
  • 刷新,搞定!

編寫我的后臺(tái)

  1. 大部分的插件編寫都是先從后臺(tái)開始的,因?yàn)楹笈_(tái)功能比較簡(jiǎn)單,無(wú)非就是“設(shè)置”和“管理”,就當(dāng)熱身了
  2. 說到“設(shè)置”,就不能不說 PwConfigSet 這個(gè)類庫(kù)了,使用她,輕松搞定,別忘了 插件配置規(guī)范 哦
  3. 附后臺(tái)源碼
  1. ManageController.php 后臺(tái)管理controller
  2. manage_run.htm 后臺(tái)管理模板

編寫底層服務(wù)

因?yàn)槲乙赖降资钦l(shuí)動(dòng)了我一下,所以我需要建一張表來記錄這些數(shù)據(jù),數(shù)據(jù)表設(shè)計(jì)如下,別忘了 數(shù)據(jù)庫(kù)命名規(guī)范 哦:

CREATE TABLE `pw_app_dongta` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `act` tinyint(1) unsigned NOT NULL default '0',
  `touid` int(10) unsigned NOT NULL default '0',
  `created_userid` int(10) unsigned NOT NULL default '0',
  `creaed_username` varchar(15) NOT NULL default '',
  `created_time` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `idx_touid_createdtime` (`touid`,`created_time`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
  1. 找到自動(dòng)建立的Dao,Dm,Ds示例文件,發(fā)現(xiàn)文件名稍微不一樣,沒關(guān)系,改一下
  2. 接下來,就是coding,這里可以參考應(yīng)用開發(fā)步驟。附底層服務(wù)源碼,別忘了 類命名(文件名)規(guī)范 哦:
  1. App_Dongta_Dao
  2. App_Dongta_Dm
  3. App_Dongta

當(dāng)然,在實(shí)際開發(fā)過程中,這一步很少能一口氣寫完的;沒關(guān)系,需要的時(shí)候,回過頭來繼續(xù)完善。

編寫我的前臺(tái)主頁(yè)面

哈哈,終于到了,最關(guān)鍵的地方了,這里就是各位自由發(fā)揮的地方了

  • 我的插件功能很簡(jiǎn)單,但是還是有幾個(gè)地方不能忘記
  1. 后臺(tái)設(shè)置了關(guān)閉,前臺(tái)不能訪問
  2. 我不允許未登錄用戶訪問
//示例代碼
if (!Wekit::C('site', 'app.dongta.ifopen')) { //應(yīng)用是否關(guān)閉
	$this->showError('動(dòng)他一下應(yīng)用,關(guān)閉了');
}
if (!$this->loginUser->isExists()) { //應(yīng)用是否登錄
	$this->showError('login.not');
}
  • 繼續(xù)coding,附源碼
  1. IndexController.php 前臺(tái)controller
  2. index_run 首頁(yè)模板
  3. index_my 誰(shuí)了我頁(yè)面模板
  4. index_act ajax請(qǐng)求動(dòng)作列表模板
  • 到此,我們的獨(dú)立插件其實(shí)已經(jīng)完成了,但是為了能更好地融入到系統(tǒng)中,我們還要添加兩個(gè)鉤子!緵]錯(cuò),搶占入口,就是搶占先機(jī)!】

添加Simple-Hook

  • 找到空間個(gè)人頭像下面的鉤子 s_space_user_info
  • 找到后臺(tái)->云平臺(tái)->應(yīng)用管理->動(dòng)他一下->設(shè)計(jì)->xml 在 inject-services 項(xiàng)下面添加
<s_space_user_info>
<app_dongta>
<class>EXT:dongta.service.srv.App_Dongta_Service</class>
<loadway>load</loadway>
<method>spaceButton</method>
<expression>config:site.app.dongta.space.ifopen==1</expression>
<description>動(dòng)他一下空間按鈕</description>
</app_dongta>
</s_space_user_info>
  • 完成 App_Dongta_Service 服務(wù),附源碼:
  1. App_Dongta_Service

添加Model-Hook

  • 找到帖子閱讀頁(yè)個(gè)人頭像下面的鉤子 m_PwThreadDisplay.createHtmlAfterUserInfo
  • 找到其業(yè)務(wù)流程類 PwThreadDisplay
  • 找到其擴(kuò)展擴(kuò)展服務(wù)接口基類 PwThreadDisplayDoBase
  • 繼承基類,并實(shí)現(xiàn)相應(yīng)接口,可選擇實(shí)現(xiàn),我們這里需要兩個(gè)接口配合,分別是 createHtmlAfterUserInfo 和 runJs 接口
  • 代碼實(shí)現(xiàn),附源碼 App_Dongta_ThreadDisplay
  • 該鉤子的注冊(cè)方式為
<m_PwThreadDisplay>
<app_dongta>
<class>EXT:dongta.service.srv.App_Dongta_ThreadDisplay</class>
<description>動(dòng)他一下帖子頁(yè)按鈕</description>
</app_dongta>
</m_PwThreadDisplay>
但是,該注冊(cè)方式注入的鉤子是伴隨PwThreadDisplay類的啟動(dòng)而自動(dòng)啟動(dòng)的,所以一般用該方式注冊(cè)的,都是偏內(nèi)在邏輯處理的。顯然,我們這里主要是展示內(nèi)容的,這個(gè)我們就要用到我們下一個(gè)此類鉤子的注冊(cè)方式

添加Controller-Hook

  • 由于Model-Hook的自動(dòng)啟動(dòng)特性,讓重用一個(gè)業(yè)務(wù)流程變得困難
  • 自動(dòng)注入的擴(kuò)展類沒有跟外部輸入交互的能力
  • 所以為了解決這兩個(gè)問題,就出現(xiàn)了Controller-Hook
  • 通常在實(shí)例化業(yè)務(wù)流程類時(shí),會(huì)有如下類似代碼
$threadDisplay = new PwThreadDisplay($tid, $this->loginUser);
$this->runHook('c_read_run', $threadDisplay);
  • 該鉤子的注冊(cè)方式為
<c_read_run>
<app_dongta>
<class>EXT:dongta.service.srv.App_Dongta_ThreadDisplayDoDongtaInjector</class>
<method>run</method>
<expression>config:site.app.dongta.read.ifopen==1</expression>
<description>動(dòng)他一下帖子頁(yè)按鈕</description>
</app_dongta>
</c_read_run>
runHook就是將App_Dongta_ThreadDisplayDoDongtaInjector類中run方法生成的擴(kuò)展服務(wù)類注入到$threadDisplay,注入后,跟使用 m_PwThreadDisplay方式是一樣的
  • Controller-Hook中class的要求
  1. 必須繼承PwBaseHookInjector,那么在這個(gè)類中就可以跟controller一樣使用$this->getInput方法接收外部參數(shù)了
  2. 必須返回一個(gè)滿足業(yè)務(wù)流程類需求的擴(kuò)展服務(wù)類

終于完成了

關(guān)鍵詞:phpwind

贊助商鏈接:

推薦文章