專(zhuān)業(yè)開(kāi)發(fā)指南drupal6中文版_第1頁(yè)
專(zhuān)業(yè)開(kāi)發(fā)指南drupal6中文版_第2頁(yè)
專(zhuān)業(yè)開(kāi)發(fā)指南drupal6中文版_第3頁(yè)
專(zhuān)業(yè)開(kāi)發(fā)指南drupal6中文版_第4頁(yè)
專(zhuān)業(yè)開(kāi)發(fā)指南drupal6中文版_第5頁(yè)
已閱讀5頁(yè),還剩479頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

總1Drupal23,動(dòng)作,4Drupal5Drupal6Drupal7Drupal第8章系9Drupal1213Drupal14151619XML-20序在一年多以前,我為本書(shū)的第一版寫(xiě)了序言。那時(shí),在Drupal世界里缺少的就是一本開(kāi)發(fā)。通過(guò)編寫(xiě)本書(shū)的第一版,有一本第一版的Drupal專(zhuān)業(yè)開(kāi)發(fā)指南。Drupal,通過(guò)它的開(kāi)源本性,已經(jīng)成為了一個(gè)偉大的軟件,這比我預(yù)期的要好很多。Drupal開(kāi)發(fā)者社區(qū)勇于創(chuàng)新,同時(shí)以極大的熱情擁抱web開(kāi)發(fā)的每個(gè)技術(shù),并努力為web開(kāi)發(fā)者提供近乎無(wú)限的可能性。在Drupal社區(qū)中,變是永過(guò)700多的開(kāi)發(fā)者為Drupal6的代碼貢獻(xiàn)了力量。通過(guò)共同努力,我們對(duì)系統(tǒng)作了重要改進(jìn),對(duì)多語(yǔ)言提供API、JavaScriptDrupal5相比,Drupal6是一個(gè)更優(yōu)秀的web應(yīng)用開(kāi)發(fā)平臺(tái)。開(kāi)發(fā)者。所以,如果對(duì)于Drupal6還缺少什么的話(huà),那么它就是本書(shū)了,我非常感謝John修訂并擴(kuò)展了本書(shū)。們,我們專(zhuān)注于Drupal的穩(wěn)定、靈活、強(qiáng)大。我非常樂(lè)意去評(píng)估和提交你的Drupal補(bǔ)丁,我敢肯定其他的DriesDrupal關(guān)于作JOHNVANDYKBell&HowellAppleIILittleBrickOut,打印和檢查BASIC代碼,以增加paddle寬度。在發(fā)現(xiàn)Drupal以前,John參與了UserLandFrontier社區(qū),并Ruby編寫(xiě)了自己的內(nèi)容管理系統(tǒng)(和MattWestgate)。John是一web架構(gòu)師,效力Lullabot,一個(gè)著名的Drupal教育和咨詢(xún)公司。在此以前,JohnIowa州立科技大學(xué)的昆蟲(chóng)系工作,他是一名系統(tǒng)分析員和助理教授。他的是關(guān)于鹿鳴的耐寒性的,他的博士關(guān)于正在研究的使用相片來(lái)創(chuàng)建3維虛擬昆蟲(chóng)。技術(shù)審稿ROBERTDOUGLASS的Drupal探索始于2003年,他創(chuàng)建了自己的個(gè)人RobsH。在2005年,他與人合著了使用Drupal,phpBB,和WordPress構(gòu)建社區(qū)。作為第一本深度講解Drupal的書(shū)籍,它為Drupal的初學(xué)者DrupalDrupal致這包括,BrandonBergren,?ivindBinde,Larry“Crell”Garfield,DmitriGaskin,Gordon,GerhardKillesreiter,GregKnaddison,Druplicon,RobLoach,ChadPhillips,OlegTerenchuck.。對(duì)于那些做出貢獻(xiàn)而在RobertDouglassKárolyNégyesiAddisonBerryAngelaByron,HeineDeelstra,JeffEaton,NathanHaug,KevinHemenway,GáborHojtsy,BarryJaspan,Earl,和JamesWalker認(rèn)真的檢查了本書(shū)的全部或部分手稿,感謝Apress小組在示例代碼需要不斷修改時(shí)的和理解,以及魔術(shù)般的將我的手稿轉(zhuǎn)變?yōu)榱艘槐緯?shū)籍。導(dǎo)這就是我們的經(jīng)歷,你可能也會(huì)遇到類(lèi)似的情況。旅程的終點(diǎn)讓人感到欣慰——成千上萬(wàn)的開(kāi)發(fā)者在為同一個(gè)項(xiàng)3種讀者。首先,這里有大量的插圖,包括各種圖表和流程圖;還有許多內(nèi)容Drupal是什樣你很快就會(huì)熟悉Drupal了。最后,本書(shū)包含了大量的評(píng)論、提示、還有對(duì)代碼的詳細(xì)解釋?zhuān)@將整本書(shū)有機(jī)的聯(lián)系到了一起。這適用于想成為Drupal高手的人。最后,你可以從htt 到本書(shū)的示例代碼,流程圖和。祝您好運(yùn)并歡迎來(lái)到Drupal社區(qū)!中文版說(shuō) 版方的,翻譯文檔學(xué)習(xí)參考使用,私自或用于商業(yè)目的。由此造成的任何糾紛和本人概不負(fù)責(zé)。第一Drupal的工作原在本章中,為你展示Drupal的概貌。會(huì)在以后章節(jié)中,對(duì)Drupal中的每個(gè)部分的工作原理進(jìn)行詳細(xì)的介紹。在這里,討論Drupal運(yùn)行所用到的技術(shù)堆棧,Drupal包含的各種文件,和Drupal使用的各種不同的概念術(shù)語(yǔ),比如節(jié)點(diǎn),鉤子,區(qū)塊和。什么是Drupal是用來(lái)構(gòu)建的。它是一個(gè)高度模塊化,開(kāi)源的web內(nèi)容管理框架,并且非常注重合作,互動(dòng)的重要性。它的特點(diǎn)包括可擴(kuò)展性強(qiáng),符合標(biāo)準(zhǔn),追求簡(jiǎn)潔代碼,內(nèi)核精練。Drupal自帶了一些基本的功能,其它的額外功能可通模塊來(lái)完成的,而不是修改組件中的代碼。它還將內(nèi)容管理和內(nèi)容表示這二者進(jìn)行了成功的分離。個(gè)報(bào)紙;一個(gè)圖庫(kù);一個(gè)內(nèi)部網(wǎng),Drupal的應(yīng)用非常廣泛,這里僅僅提到了其中的一部分。它甚至可用于教育。著Drupal系統(tǒng);可參看和。技術(shù)堆使用最流行的技術(shù),而后者則意味著嚴(yán)謹(jǐn)?shù)木幋a。Drupal的技術(shù)堆棧如圖1-1所示。操作系統(tǒng)位于技術(shù)堆棧的最底層,Drupal基本不用關(guān)心底層的操作系統(tǒng)。只要它支持PHP,就可以運(yùn)行Drupal。的這種長(zhǎng)期的友Drupal的根下自帶了一個(gè).htaccess,用來(lái)確Drupal安裝的安全以使Apache的mod_rewrite模塊來(lái)實(shí)現(xiàn)簡(jiǎn)潔(Clean)URLs將URL中的“?”,“&”以及其它奇怪的符號(hào)清除掉,在Drupal中去掉的是“?q=”。這一點(diǎn)特別重要,當(dāng)從其它的內(nèi)容管理系統(tǒng)或者靜態(tài)文件中遷移到Drupal上時(shí),依照TimBerners-LeeMySQL和PostgreSQL,不過(guò)對(duì) SQL和Oracle的支持也在不斷增加。影響。然而,PHP也可以用于構(gòu)建嚴(yán)謹(jǐn)?shù)拇a。Drupal中的所有代碼都遵守了嚴(yán)格的編碼規(guī)范PHP的門(mén)檻比較低,這就意味著有的人能夠?yàn)镈rupal貢獻(xiàn)代碼,通過(guò)開(kāi)源,會(huì)有很多人對(duì)這些Drupal的是由一個(gè)輕量級(jí)的框架構(gòu)成的。當(dāng)你從Drupal時(shí),得到的就是Drupal。它負(fù)責(zé)提供用戶(hù)管理、分類(lèi)、和模板,如圖1-2所示。圖1-2Drupal內(nèi)核的概貌(沒(méi)有展示完所有的功能管理界面(rt efc)Drupal的管理界面與站點(diǎn)的前臺(tái)部分緊密的集成在了一起,并且在默認(rèn)情況下,使用相同的。第用戶(hù)區(qū)塊(參看“區(qū)塊”部分)中看到管理站點(diǎn)的一個(gè)。點(diǎn)擊這一,你將進(jìn)入到Drupal的管理界面。根據(jù)用戶(hù)對(duì)站點(diǎn)權(quán)限的不同,每個(gè)用戶(hù)的區(qū)塊都會(huì)有一個(gè)不同的。模塊DrupalDrupal3方模塊,編寫(xiě)自己的模塊。這樣,就可以根據(jù)1-3所示。圖1-3通過(guò)啟用其它模塊來(lái)添加的功鉤子塊名”+“鉤子名”——comment_user()locale_user(),節(jié)點(diǎn)模塊中塊系統(tǒng)(Drupal鉤子)”。的模板方式,比如Smarty,PHP模板屬性語(yǔ)言(PHPTAL),和PHPTemte。在Drupal中可以使用多種方式來(lái)為你的定制外觀。最簡(jiǎn)單的方式是使用CSS來(lái)覆蓋Drupal內(nèi)置的類(lèi)和ID然而,HTML輸出時(shí),你會(huì)發(fā)現(xiàn)很容易就可以實(shí)現(xiàn)你的目標(biāo)。Drupal的模板文件由標(biāo)準(zhǔn)的HTML和PHP組成。另外,Drupal頁(yè)面的每個(gè)動(dòng)態(tài)部分(比如盒子、列表、或者面包屑),都可以通過(guò)一個(gè)具有合適名字的函數(shù)進(jìn)行覆寫(xiě)。接著,Drupal將使用你的函數(shù)來(lái)創(chuàng)建頁(yè)面的該部分。節(jié)點(diǎn)區(qū)塊(區(qū)塊是在你模板的特定位置上,可以啟用或者禁用的信息。例如,一個(gè)區(qū)塊可以用來(lái)顯示你站點(diǎn)當(dāng)前用戶(hù)的人數(shù)。文件布局( 通過(guò)了解Drupal默認(rèn)安裝的 的Drupal安裝輪廓。一個(gè)Drupal默認(rèn)安裝的 結(jié)構(gòu)如圖1-4所示。 )下面的任何東西,你要添加的其它模塊須放到sites 安裝成為一個(gè)電子商務(wù)平臺(tái)。scripts:包含了許多,這些可用于語(yǔ)法檢查,代碼清潔,從命令行運(yùn)行Drupal,使用cron處理特定情況等等。在Drupal的請(qǐng)求生命周期中,用不到它;里面包含一些s和Perl的實(shí)用sites:包含了你對(duì)Drupal所進(jìn)行的修改,包括設(shè)置、模塊、等形式(參看圖1-5)。你從第3方模塊庫(kù)中的模塊,或者你自己編寫(xiě)的模塊,都放在sites/all/modules下面。這使得你對(duì)Drupal所進(jìn)行的任何修改都保存在單個(gè)文件夾里。在sites下面有一個(gè)名為default的子,里面包含了你的Drupal站點(diǎn)的默認(rèn)的設(shè)置文件default.settings.php。會(huì)拷貝默認(rèn),并將其重命名為你站點(diǎn)的URL,所以你最終的設(shè)置文件就位于 web服務(wù)器需要具有對(duì)這個(gè)子進(jìn)行讀和寫(xiě)的權(quán)限。如果可以的話(huà),Drupal的安裝器將會(huì)為你自動(dòng)的創(chuàng)建這個(gè)子,并update.phpDrupal版本升級(jí)后,用來(lái)更新數(shù)據(jù)庫(kù)模式(schema)服務(wù)一個(gè)請(qǐng)求( 當(dāng)Drupal收到一個(gè)請(qǐng)求時(shí)都發(fā)生了什么呢?如果對(duì)此能有一個(gè)概括性的了解,那么對(duì)以后的學(xué)習(xí)將會(huì)很有幫助,所以本部Web服務(wù)器的角色(TheWebServer’sPHP設(shè)置,并啟用簡(jiǎn)潔URL。基本上對(duì)Drupal的所有調(diào)用都是從index.php開(kāi)始的。例如,調(diào)用在我們的例子中,路經(jīng)就為foo/bar。 這一流程的結(jié)果就是,Drupal對(duì) /foo/bar和 的處理方式是一樣的,因?yàn)閷?duì)于Drupal來(lái)說(shuō),這兩者的內(nèi)部路徑是一樣的。這就使得Drupal可以使用不帶“?q=”的URL了。這些URL被稱(chēng)為簡(jiǎn)潔URL。在備選的web服務(wù)器中,比如微軟的IIS,可以使ISAPI模塊比如ISAPI_Rewrite來(lái)實(shí)現(xiàn)簡(jiǎn)潔URL。IIS7及引導(dǎo)指令流程 or 引導(dǎo)指令流程(Theotsrp初始配置(ofuo)DrupalURL($base_url)include_once()來(lái)解析前期頁(yè)面緩存(ElPage文件則通過(guò)將cache_inc變量設(shè)置為文件的路徑來(lái)定義。具體示例可參看緩存一章。初始化數(shù)據(jù)庫(kù)(Initialize基于主機(jī)名/ID地址進(jìn)行控制(Hostname/IP-BasedAccessControl)Drupal支持基于主機(jī)名/IP地址來(lái)主機(jī)(對(duì)站點(diǎn)的)。在控制階段,會(huì)快速的檢查請(qǐng)求是否來(lái)自一個(gè)被禁初始化會(huì)話(huà)處理(InitializeSession階段,將初始化或者重新構(gòu)建會(huì)話(huà)。代表當(dāng)前用戶(hù)的全局對(duì)象$User也會(huì)在這一階段初始化,不過(guò)出去效率的原因,并不是對(duì)象的所有屬性都是可用的(當(dāng)需要時(shí),可以通過(guò)明確的調(diào)用函數(shù)user_load()來(lái)加載這些屬性)。后期頁(yè)面緩存(LatePage在后期頁(yè)面緩存階段,Drupal會(huì)加載足夠的支持代碼,來(lái)決定是否需要從頁(yè)面緩存中提供一個(gè)頁(yè)面。這包括,把來(lái)自于語(yǔ)言判定(Language路徑處理Drupal內(nèi)部路徑的緩存和查找操作。完成該階段是引導(dǎo)指令的最后一個(gè)階段,它包括加載一個(gè)通用函數(shù)庫(kù),支持,和支持回調(diào)映射,文件處理,Unicode,PHPDrupal定制的錯(cuò)誤處理器,并加載所有啟用了的模塊。最后Drupal調(diào)用init鉤子,這樣在對(duì)請(qǐng)求正式開(kāi)始處理以前,將有機(jī)會(huì)通知相應(yīng)的模塊。Drupal整個(gè)引導(dǎo)指令完成以后,那么框架中的所有部分現(xiàn)在都可以使用了?,F(xiàn)在就可以獲得瀏覽器的請(qǐng)求并將它控制。模塊使用菜單鉤子來(lái)它們的回調(diào)函數(shù)(信息,參看第4章)處理一個(gè)請(qǐng)求(Processinga括,將從數(shù)據(jù)庫(kù)中取回該節(jié)點(diǎn)的數(shù)據(jù),并將它放到一個(gè)數(shù)組中。接著,就到了化的時(shí)候了?;瘮?shù)據(jù)(Themingthe選用的,來(lái)為網(wǎng)頁(yè)提供一個(gè)合適的外觀,并將生成的HTML返回給web瀏覽器。總結(jié)服務(wù)處理流程的各個(gè)部分,會(huì)在后面章節(jié)中作出詳細(xì)介紹。2建一個(gè)模塊在許多開(kāi)源的應(yīng)用中,你可以通過(guò)修改源代碼來(lái)定制應(yīng)用。這是法,用來(lái)獲得你想要的功能;但是在drupal中,一般不贊成這樣做,只有在萬(wàn)不得已的情況下才使用這一。修改源代碼,意味著隨著Drupal的每次更新,你必須要做的工作你必須測(cè)試一下你的修改是否還能正常工。代替的,Drupal的設(shè)計(jì)從底層便考慮了模塊化和擴(kuò)展性。modules下面。現(xiàn)在看一下這個(gè)子,然后導(dǎo)航到“管理??模塊”,比較一下子下的模塊與管理界面上在本章,從頭開(kāi)始創(chuàng)建一個(gè)模塊;在你創(chuàng)建模塊時(shí),你將學(xué)到模塊必須遵守的一些標(biāo)準(zhǔn)。我們管理員啟用了評(píng)論模塊,那么用戶(hù)可能會(huì)對(duì)內(nèi)容評(píng)論。但是如果是在一個(gè)網(wǎng)頁(yè)上添加一個(gè)注釋?zhuān)ㄒ环N 創(chuàng)建相應(yīng)的文置這個(gè)模塊。我們可以把這個(gè)模塊放在模塊所在的中去,不過(guò)這樣的話(huà),我們需要記住哪些是模塊,哪些是我們的模塊,這樣一來(lái),就增加了成本。讓我們把它放在sites/all/modules下面,以將其與模塊區(qū)分開(kāi)來(lái)。sites/all/modules/custom下面創(chuàng)建一個(gè)名為annotate的。這樣就可以將你開(kāi)發(fā)的自定義模塊與你的第3方模塊區(qū)分開(kāi)了。如果有一天,你需要將你的委托給另一個(gè)開(kāi)發(fā)者,那么這一點(diǎn)還是很有幫助的,不過(guò)是否將它;name=description=Allowsuserstoannotatenodes.core=6.xpackage=ProDrupal這個(gè)文件的格式非常簡(jiǎn)單,在這里一個(gè)鍵對(duì)應(yīng)一個(gè)值。我們從版本管理系統(tǒng)(CVS)的標(biāo)識(shí)開(kāi)始。如果我們想和其他用戶(hù)這一模塊,通過(guò)將它提交到Drupal的第3方模塊中,這個(gè)值將會(huì)被CVS自動(dòng)替換。接著,我們?yōu)镈rupal提供決定的;這樣,如果我們有3個(gè)不同的模塊,它們都有package=ProDrupalDevelopment,那么它們將被放在同一組中。PHP5.2,依賴(lài)于;name=Forumdescription=Randomlyreassignsrepliestodifferentdiscussionthreads.core=6.xdependencies[]=forumpackage="EvilBob'sForumBonusPak"php=5.2你可能會(huì)想,為什么我們需要一個(gè)單獨(dú)的.info文件呢?為什么不在我們的主模塊中寫(xiě)一個(gè)函數(shù)來(lái)返回這些元數(shù)據(jù)呢?超出分配給PHP的內(nèi)存上限?,F(xiàn)在我們準(zhǔn)備好創(chuàng)建一個(gè)實(shí)際的模塊了。在你的sites/all/modules/custom/annotate //LetsusersaddprivateannotationstoAddsatextfieldwhenanodeisdissothatauthenticatedusersmaymake描述。注意,我們?cè)谶@里有意的不使用結(jié)束?>;這對(duì)于PHP來(lái)說(shuō)是可選的,如果包含了它,就可能導(dǎo)致文件的尾部空格問(wèn)題(參看)。注意為什么我們?cè)谶@里這么詳細(xì)的講述每一個(gè)細(xì)節(jié)?這是因?yàn)?,如果?lái)自世界各地的成百上千的人開(kāi)發(fā)同一個(gè)項(xiàng)目的話(huà),DrupalDrupal開(kāi)發(fā)用戶(hù)手實(shí)現(xiàn)一個(gè)含菜單項(xiàng)的數(shù)組。每一項(xiàng)(我們這里只有一項(xiàng))都以路徑為鍵,在這里就是admin/settings/annotate。菜單項(xiàng)的值是一個(gè)數(shù)組,里面包含的鍵和值是用來(lái)描述在該路徑被請(qǐng)求時(shí)Drupal要做什么的。這方面的詳細(xì),可參看第4章Implementationofhook_functionannotate_()$items['admin/settings/annotate']=array('title'=>'Annotationsettings','description'=>'Changehowannotationsbehave.','pagecallback'=>'drupal_get_form','pagearguments'=>array('annotate_admin_settings'),'accessarguments'=>array('administersiteconfiguration'),'type'=>_NORMAL_ITEM,'file'=>return}此時(shí)不要過(guò)于關(guān)注這里的具體細(xì)節(jié)。這段代碼說(shuō),“當(dāng)用戶(hù)訪(fǎng)問(wèn)頁(yè)面/?q=admin/settings/annotatedrupal_get_form并向它傳遞了一個(gè)表單otate_ad_eotatamc中查找描述該表單的函數(shù)。只有具有管理站點(diǎn)配置權(quán)限的用戶(hù)al(Dal數(shù)?,F(xiàn)在你應(yīng)該清楚我們?yōu)槭裁窗阉凶鱤ook_()或者菜單鉤子了??梢酝ㄟ^(guò)在鉤子的名字前加上你的模塊名來(lái)創(chuàng)建Drupal鉤子。提示Drupal的鉤子幾乎允許你修改這個(gè)軟件的任何方面。你可以在Drupal的API文檔站點(diǎn)()上,找到Drupal鉤子的完整列表和它們的使用說(shuō)明。添加特定于模塊的呈現(xiàn)一組復(fù)選框,每一個(gè)復(fù)選框就對(duì)應(yīng)一個(gè)已有的內(nèi)容類(lèi)型。這樣終端用戶(hù)就可以通過(guò)選中或者取消選中復(fù)選框(21所示otatmoe文件里,而對(duì)于每個(gè)置表單,所以創(chuàng)建文件sites/all/modules/custom/annotate/annotate.admin.inc,并向里面添加以下代碼://Administrationpagecallbacksfortheannotate@ingroup@seefunctionannotate_admin_settings()//Getanarrayofnodetypeswithinternalnamesaskeys//"friendlynames"asvalues.//array('page'=>'Page','story'=>$options=$form['annotate_node_types']=array('#type'=>'checkboxes','#title'=>t('Usersmayannotatethesecontenttypes'),'#options'=>$options,'#description'=>t('Atextfieldwillbeavailableonthesecontenttypes tomakeuser-specificreturn}選框。我們?cè)谧兞?options中已經(jīng)得到了帶鍵的數(shù)組。'page'=>'Page','story'=>一個(gè)名為“SavoryRecipe”的節(jié)點(diǎn)類(lèi)型,那么數(shù)組看起來(lái)應(yīng)該這樣:'page'=>'Page','savory_recipe'=>'SavoryRecipe','story'=>因此,在我們web表單中,為節(jié)點(diǎn)類(lèi)pagestory生成了相應(yīng)的復(fù)選框。我們通過(guò)定義屬性#title的值,為表單元素設(shè)置了一個(gè)標(biāo)題。在多于一個(gè)的復(fù)選框),所以#default_value的值將會(huì)是一個(gè)數(shù)組。用來(lái)大量的數(shù)據(jù)。對(duì)于配置屬性這樣簡(jiǎn)單數(shù)值的,它卻是一個(gè)非常方便的系統(tǒng)。注意我們傳遞給varialble_get()注釋的節(jié)點(diǎn)類(lèi)型。在默認(rèn)情況下,我們?cè)试S對(duì)節(jié)點(diǎn)類(lèi)型page進(jìn)行注釋。保存你剛創(chuàng)建的文件,然后導(dǎo)航到“管理??模塊”proDrupalDevelopment的組中,在模塊sites/all/modules/custom中)。繼續(xù)前進(jìn),啟用你的新模塊。圖2-1,annotate.module盡管代碼中的一行有點(diǎn)太長(zhǎng)了,但是沒(méi)有關(guān)系,你現(xiàn)在應(yīng)該能夠感受到撬動(dòng)Drupal的力量了。添加數(shù)據(jù)(譯者注:這里的筆記就是注釋的意思Implementationoffunctionannotate_nodeapi(&$node,$op,$teaser,{global$user;switch($op){//The'view'operationmeansthenodeisabouttobedisyed.case'view'://Abortiftheuserisananonymoususer(notloggedin)//ifthenodeisnotbeingdisyedonapageby//(forexample,itcouldbeinanodelistingorsearchresult).if($user->uid==0||!$page){}//Findoutwhichnodetypesweshould$types_to_annotate=variable_get('annotate_nodetypes',//Abortifthisnodeisnotoneofthetypesweshouldannotate.if(!in_array($node->type,$types_to_annotate)){}//Addourformasacontent'#value'=>drupal_get_form('annotate_entry_form',$node),'#weight'=>10}}這個(gè)看起來(lái)有點(diǎn)復(fù)雜,所以讓我們?cè)敿?xì)的分析一下。首先要注意的是,我們?cè)谶@里實(shí)現(xiàn)了Drupal的另一個(gè)鉤子。這次是 在我們的代碼被調(diào)用時(shí)在Drupal中將發(fā)生什么。這些信息保存在了參數(shù)$op中,它可以是接下來(lái),我們快速的檢查了一些我們不想顯示注釋字段的情況。一種情況是$user對(duì)象的用戶(hù)ID為0時(shí),這意味著查看節(jié)點(diǎn)的用戶(hù)此時(shí)沒(méi)有登錄(global將$user對(duì)象包含了進(jìn)來(lái),這樣我們就可以測(cè)試當(dāng)前用戶(hù)是否登錄了)。另一種情況是當(dāng)參數(shù)$page不為T(mén)RUE時(shí),我們想表單的顯示。如果它為FALSE,這意味著,這個(gè)節(jié)況下,我們不需要添加任何東西。我們使用break語(yǔ)句來(lái)跳出switch語(yǔ)句從而對(duì)頁(yè)面的修改。如果節(jié)點(diǎn)類(lèi)型不是我們想要注釋的,使用break語(yǔ)句來(lái)跳出switch語(yǔ)句。將在annotate.module中的一個(gè)單獨(dú)的函數(shù)中完成這件事,它唯一的責(zé)任就是定義表單:Definetheformforenteringanfunctionannotate_entry_form($form_state,$node)//Definea$form['annotate']array('#type'=>'fieldset','#title'=>t('Annotations'),//Defineatextareainsidethe$form['annotate']['note']=array('#type'=>'textarea','#title'=>t('Notes'),'#default_value'=>isset($node->annotation)?$node->annotation:'#description'=>t('Makeyour alannotationsaboutthiscontent here.Onlyyou(andthesiteadministrator)willbeabletoseethem.')//Forconvenience,savethenode$form['annotate']['nid']=array('#type'=>'value','#value'=>$node->nid,//Defineasubmit$form['annotate']['submit']=array('#type'=>'submit','#value'=>t('Update'),return}它傳遞給了drupal_get_form()。我們創(chuàng)建表單的方式,和我們?cè)诤瘮?shù)annotate_admin_settings()中使用的一樣,都是創(chuàng)建一個(gè)鍵值數(shù)組 頁(yè)面的下面,所以我們?yōu)樗峙淞艘粋€(gè)相對(duì)較大的重量10.我們要顯示的是我們的表單,所以我們調(diào)用函數(shù)2-2drupalweb把數(shù)據(jù)到數(shù)據(jù)庫(kù)表模塊所用數(shù)據(jù)的最常用方式,就是為這個(gè)模塊的數(shù)據(jù)創(chuàng)建一個(gè)單獨(dú)的數(shù)據(jù)庫(kù)表。這將使得該數(shù)據(jù)與drupal數(shù)據(jù)庫(kù)SQL語(yǔ)句如下所示:CREATETABLE(uidint(10)NOTNULL,nidint(10)NOTNULL,notelongtextNOTNULL,whenint(11)NOTNULLdefault'0',PRIMARYKEY(uid,nid),則使用.install,所以對(duì)于annotate.module,這個(gè)文件名應(yīng)該為annotate.install。創(chuàng)建文件//Implementationoffunctionannotate_install()//UseschemaAPItocreatedatabasetable.}Implementationoffunctionannotate_uninstall()//UseschemaAPItodeletedatabasetable.//Deleteourmodule'svariablefromthevariablestable.}Implementationoffunctionannotate_schema()$schema['annotations']='description'=>t('Storesnodeannotationsthatuserswrite.'),'fields'=>array('nid'array('type'=>'notnull'=>TRUE,'default'=>0,'description'=>t('The{node}.nidtowhichthe 'uid'array('type'=>'notnull'=>TRUE,'default'=>0,'description'=>t('The{user}.uidoftheuserwhocreated 'note'=>'description'=>t('Thetextoftheannotation.'),'type'=>'text','notnull'=>TRUE,'size'=>'big''created'=>'description'=>t('AUnixtimestampindicatingwhentheannotationwascreated.'),'type'=>'notnull'=>TRUE,'default'=>0'primarykey'=>array('nid','uid'return}在第一次啟用注釋模塊時(shí),drupal會(huì)查找文件annotate.install并運(yùn)行函數(shù)annotate_install(),它將我們?cè)谀J姐^DrupalDrupal將它們轉(zhuǎn)化為了我們當(dāng)前所用數(shù)據(jù)站點(diǎn)構(gòu)建如果前面的辦法無(wú)效的話(huà),那么還有最后的,那就是在數(shù)據(jù)庫(kù)的system表中直接刪除該模塊的記錄。Handlesubmissionoftheannotationformandofthedatatothefunctionannotate_entry_form_submit($form,{global$note=$nid=db_query('DELETEFROM{annotations}WHEREnid=%dANDuid=$nid,$user-db_query("INSERTINTO{annotations}(nid,uid,note,created)VALUES(%d,%d,'%s',%d)",$nid,$user->uid,$note,time());drupal_set_message(t('Yourannotationhasbeen}以無(wú)縫的實(shí)現(xiàn)數(shù)據(jù)庫(kù)表的前綴化(關(guān)于表前綴化的詳細(xì),可參看文件sites/default/settings.php中的注釋?zhuān)?。第三,在用?hù)的會(huì)話(huà)中,在用戶(hù)查看的下一個(gè)頁(yè)面時(shí),它就會(huì)被Drupal作為一個(gè)通知顯示給用戶(hù)。這樣,用戶(hù)就獲得一些反饋信我們的表單。在我們把我們的表單分配給$node->content的代碼前面,我們添加以下代碼,這里用粗體將其標(biāo)出了:Implementationoffunctionannotate_nodeapi(&$node,$op,$teaser,{global$user;switch($op){//The'view'operationmeansthenodeisabouttobedisyed.case'view'://Abortiftheuserisananonymoususer(notloggedin)//ifonlythenodesummary(teaser)isbeingdisyed.if($user->uid==0||!$page){}//Findoutwhichnodetypesweshould$types_to_annotate=variable_get('annotate_node_types',//Abortifthisnodeisnotoneofthetypesweshouldannotate.if(!in_array($node->type,$types_to_annotate)){}//Getthecurrentannotationforthisnodefromthe//andstoreitinthenode$result=db_query('SELECTnoteFROM{annotations}WHEREnid=%dANDuid=%d',$node->nid,$user->uid);$node->annotation=//Addourformasacontent'#value'=>drupal_get_form('annotate_entry_form',$node),'#weight'=>10casedb_query('DELETEFROM{annotations}WHEREnid=%d',$node->nid);}}塊。在通往Drupal專(zhuān)業(yè)開(kāi)發(fā)者的道,你已經(jīng)邁出了關(guān)鍵的一步。定義你自己的管理么你可以非常容易的創(chuàng)建一個(gè)。在這個(gè)例子中,我們創(chuàng)建一個(gè)名為“Nodeannotation”的新類(lèi)別。為了實(shí)現(xiàn)這一點(diǎn),我們修Implementationof function ()array('title'=>'Node'description'=>'Adjustnodeannotationoptions.','position'=>'right','weight'=>-'pagecallback'=>'system_admin_ 'accessarguments'=>array('administersiteconfiguration'),'file'=>'system.admin.inc','filepath'=>drupal_get_path('module',$items['admin/annotate/settings']=array('title'=>'Annotationsettings','description'=>'Changehowannotationsbehave.','pagecallback'=>'drupal_get_form','pagearguments'=>array('annotate_admin_settings'),'accessarguments'=>array('administersiteconfiguration'),'type'=>_NORMAL_ITEM,'file'=>return}圖2-3指向注釋模塊設(shè)置的現(xiàn)在作為一個(gè)單獨(dú)的類(lèi)別出現(xiàn)有多種方式:可以直接清空cache_表,或者使用Drupal的開(kāi)發(fā)模塊(devel.module)所提供的“重構(gòu)菜單”,或者導(dǎo)航到“管理?站點(diǎn)配置?性能”并點(diǎn)擊“清除緩存數(shù)據(jù)”按鈕。sites/all/modules/devel,接著啟用該模塊,然后導(dǎo)航到“管理??區(qū)塊”,啟用它的開(kāi)發(fā)區(qū)塊。路徑(admin/annotate)。我們:它應(yīng)該放在右欄中,重量為-5,這樣它就恰好位于“站點(diǎn)配置”類(lèi)別的上面,從而方便了截圖,如圖2-3所示的。第二步是告訴Drupal,把指向注釋設(shè)置的實(shí)際放在類(lèi)別“Nodeannotation”的內(nèi)部。我們通過(guò)修改原有菜單項(xiàng)的單項(xiàng)是“站點(diǎn)配置”類(lèi)別路徑admin/settings的孩子,如表2-1所示。當(dāng)Drupal重新構(gòu)造菜單樹(shù)時(shí),它查找路徑來(lái)為父菜單菜單項(xiàng)建立繼承關(guān)系,由于admin/annotate/settings是admin/annotate的孩子,這決定了要像圖2-3那樣顯示。將模塊菜單項(xiàng)嵌套在如表2-1所示的任意一個(gè)路徑下,將使模塊出現(xiàn)在Drupal管理頁(yè)面中該類(lèi)別的下面。2-1路 類(lèi) /?q=admin/annotate/settings時(shí),調(diào)用drupal_get_form('annotate_admin_settings')將被執(zhí)行,它主要是告訴Drupal構(gòu)建由函數(shù)sites/all/modules/custom/annotate/annotate.admin.inc中:Formbuilder.Configure@ingroup@seefunctionannotate_admin_settings()//Getanarrayofnodetypeswithinternalnamesaskeys//"friendlynames"asvalues.//array('page'=>'Page','story'=>$options=$form['annotate_node_types']=array('#type'=>'checkboxes','#title'=>t('Usersmayannotatethesecontenttypes'),'#options'=>$options,'#default_value'=>variable_get('annotate_node_types',array('page')),'#description'=>t('Atextfieldwillbeavailableonthesecontenttypestomakeuser-specificarray('#type'=>'#title'=>t('Annotationswillbe'#description'=>t('Selectamethodfordeletingannotations.'),'#options'=>array(//Defaulttoarray('#type'=>'textfield','#title'=>t('Annotationsper'#description'=>t('Enterthe umnumberofannotationsallowedpernode(0fornolimit).'),'#size'=>3return}2-4驗(yàn)證用戶(hù)提交的設(shè)Validatetheannotationconfigurationif(!is_numeric($limit)){form_set_error('annotate_limit_per_node',t('Pleaseentera}}入了無(wú)效數(shù)據(jù)的話(huà),那么為發(fā)生錯(cuò)誤的字段設(shè)置一個(gè)錯(cuò)誤信息,這反映為在頁(yè)面上就是顯示一個(gè)警告信息,并將包含錯(cuò)誤的字段進(jìn)行顯示,如圖2-5所示:圖2-5驗(yàn)證設(shè)置了一個(gè)錯(cuò)誤信Drupal是怎么知道要調(diào)用我們的函數(shù)呢?我們對(duì)函數(shù)名采用了特殊的方式,使用表單定義函數(shù)的名設(shè)DrupalvariablesDrupal在數(shù)據(jù)庫(kù)中有一個(gè)名為variables的表,并且鍵-值對(duì)可以使用variable_set($key,$value)來(lái),使用annotate_limit_per_node)的名字相同。命名方式為:你的模塊名加上一個(gè)描述性的名稱(chēng)。表單字段和變量的鍵應(yīng)該由于Annotationswillbedeleted”字段是一個(gè)單選按鈕,所以它看起來(lái)復(fù)雜了一點(diǎn)。這個(gè)字段的#option'#options'=>)'#options'=>[0]=>[1]=>[2]=>t('After30)=>',)//使用variable_get()來(lái)取回的//Getstoredsetting umnumberofannotationsper$max=variable_get('annotate_limit_per_node',篇外與開(kāi)源社區(qū)這一模塊,這是自然的,所以需要?jiǎng)?chuàng)建一個(gè)README.txt文件,然后把它放到annotation的 可,而上的打包將會(huì)為模塊自動(dòng)添加一個(gè)LICENSE.txt文本。接下來(lái),你就可以把它上傳到上的第3方模塊中了,然后創(chuàng)建一個(gè)項(xiàng)目頁(yè)面,用來(lái)追蹤社區(qū)中其他用戶(hù)的反饋??傁l(fā)布以后收到一封電子郵件?;蛘弋?dāng)用戶(hù)在評(píng)論中使用了詞語(yǔ),那么就會(huì)被自動(dòng)封號(hào)。本章將描Drupal的鉤子,從而當(dāng)那些發(fā)生時(shí),能夠運(yùn)行自己的代碼。使用使用理解和觸發(fā)理流程進(jìn)行交互。表3-1給出了一些Drupal。類(lèi)型創(chuàng)建一個(gè)節(jié) 節(jié)刪除一個(gè)節(jié) 節(jié)查看一個(gè)節(jié) 節(jié)創(chuàng)建一個(gè)用戶(hù)帳 用更新用戶(hù)用 登 用Drupal開(kāi)發(fā)者將這些內(nèi)部稱(chēng)為鉤子,這是因?yàn)楫?dāng)一個(gè)發(fā)生時(shí),Drupal允許模塊從該點(diǎn)鉤進(jìn)Drupal的執(zhí)行路徑。 判定對(duì)哪個(gè)Drupal做出文件,并將其放在了sites/all/modules/custom/beep/:;name=description=Simulatesasystembeep.package=ProDrupalDevelopmentcore=6.x//Provideasimulatedfunctionbeep_beep()}錄時(shí)發(fā)出嘟嘟聲。通過(guò)在我們的模塊中實(shí)現(xiàn)hook_user(),并將邏輯添加到login操作中,我們就可以完成目標(biāo)了:Implementationoffunctionbeep_user($op,&$edit,&$account,$category={if($op=='login'){}}Implementationoffunctionhook_nodeapi(&$node,$op,$a3=NULL,$a4={if($op=='insert'){}}如果我們想在添加評(píng)論時(shí),也讓Drupal發(fā)出嘟嘟聲,那又該怎么辦呢?好的,我們可以實(shí)現(xiàn) 如“用戶(hù)鉤子,登錄操作”或者“nodeapi鉤子,插入操作”。當(dāng)這些操作發(fā)生時(shí),trigger.module就會(huì)讓你觸發(fā)一個(gè)動(dòng)作。理解動(dòng)一個(gè)動(dòng)作就是Drupal要做的一些事情。下面是一些例PHP函數(shù)有觸發(fā)器用戶(hù)界導(dǎo)航到“管理??模塊”,并啟用觸發(fā)器模塊。接著導(dǎo)航到“管理??觸發(fā)器”圖3-1.不是所有的動(dòng)作對(duì)所有的觸發(fā)器都可用,這是因?yàn)橛行﹦?dòng)作在特定的上下文中沒(méi)有任何意義。例如,在觸發(fā)器“在刪除表3-2.Drupal6鉤 操 觸發(fā)器名 在刪除評(píng)論后 cron 在用戶(hù)帳戶(hù)創(chuàng)建之后 userview你的第一個(gè)動(dòng)Implementationoffunctionbeep_action_info()$info['beep_beep_action']=array('type'=>'description'=>t('Beepannoyingly'),'configurable'=>FALSE,'hooks'=>'nodeapi'=>array('view','insert','update','comment'=>array('view','insert','update','user'=>array('view','insert','update','delete','login'),'taxonomy'=>array('insert','update','delete'),return}該函數(shù)的名字為是個(gè)動(dòng)作,我們?cè)谖覀兊腷eep_beep()函數(shù)的名字后面追加了_actionbeep_beep_action()。type:這是你編寫(xiě)的動(dòng)作的類(lèi)型。Drupal使用該信息,將動(dòng)作歸類(lèi)到觸發(fā)器分配界面的下拉選擇框中??赡艿念?lèi)型包括什么對(duì)象呢?”(如果答案不確定,或者是“各種不同的對(duì)象!”,那么可以使用system類(lèi)型)。hooks:在這個(gè)鉤子數(shù)組中,每個(gè)條目都是用來(lái)列舉該動(dòng)作所支持的操作的。Drupal使用這一信息,來(lái)判定該動(dòng)作在觸發(fā)Simulateabeep.ADrupal{}分配該動(dòng)個(gè)用戶(hù)界面,如圖3-2所示。圖3-2.修改動(dòng)作所支持的觸Implementationoffunctionbeep_action_info()$info['beep_beep_action']='type'=>'description'=>t('Beepannoyingly'),'configurable'=>FALSE,'hooks'=>'nodeapi'=>return}支持所有觸發(fā)器的*Implementationoffunctionbeep_action_info()$info['beep_beep_action']array('type'=>'system','description'=>t('Beepannoyingly'),'configurable'=>FALSE,'hooks'=>'any'=>return}高級(jí)動(dòng)嘟嘟一下,這就完事了。但是許多時(shí)候,動(dòng)作可能需要一點(diǎn)的上下文。例如,一個(gè)“發(fā)送電子郵件”動(dòng)作,需要知道將電如果你想告訴Drupal你的動(dòng)作是一個(gè)高級(jí)動(dòng)作的話(huà),你需要進(jìn)行以下步驟:在你模塊的hook_action_info()實(shí)現(xiàn)中將配置表單。表3-3對(duì)簡(jiǎn)單動(dòng)作和高級(jí)動(dòng)作的區(qū)別進(jìn)行了總結(jié)。簡(jiǎn)單動(dòng)無(wú)高級(jí)動(dòng)無(wú) *如果需要的話(huà),可以使用$object和$context*Implementationoffunctionbeep_action_info()$info['beep_beep_action']=array('type'=>'description'=>t('Beepannoyingly'),'configurable'=>FALSE,'hooks'=>'nodeapi'=>array('type'=>'system','description'=>t('Beepmultipletimes'),'configurable'=>TRUE,'hooks'array('any'=>return}框中了,如圖3-3所示。圖3-3.IDIDbeep_multiple_beep_action,所以按照約定,我們?cè)诤竺孀芳犹峤缓瘮?shù)的名字為:動(dòng)作*FormforconfigurableDrupalactiontobeepmultiple$form['beeps']='#type'=>'#title'=>t('Numberof'#description'=>t('Enterthenumberoftimestobeepwhenthisaction'#default_value'=>isset($context['beeps'])?$context['beeps']:'1','#required'=>TRUE,return}if(!is_numeric($beeps)){form_set_error('beeps',t('Pleaseenteranumeric}elseif((int)$beeps>10)form_set_error('beeps',t('Thatwouldbetooannoying.Pleasechoosefewerthan10beeps.'));}}{return'beeps'=>(int)}擇添加一個(gè)高級(jí)動(dòng)作“嘟嘟多次”時(shí),如圖3-3所示,Drupal將會(huì)使用我們的表單字呈現(xiàn)一個(gè)完整的動(dòng)作配置表單,如圖3-4所示。圖3-4.動(dòng)作“嘟嘟多次”嘟五次并將其描述為“嘟嘟五次”。這樣,在將動(dòng)作分配給一個(gè)觸發(fā)器時(shí),我們就了這兩個(gè)高級(jí)動(dòng)作之間的區(qū)別。這樣,提示

*Configurableaction.Beepsaspecifiednumberof{for($i=1;$i<$context['beeps'];$i++){}}我們需要了解當(dāng)前的上下文信息,那么可以簡(jiǎn)單的將我們的簡(jiǎn)單動(dòng)作的函數(shù)簽名從beep_beep_action()改為beep_beep_action($object,$context)。所有的動(dòng)作都可以使用$object和$context參數(shù)。在動(dòng)作中使用上下::觸發(fā)器模塊是如何準(zhǔn)備上下文user.module,我們看到Drupal已經(jīng)為我們提供了這個(gè)動(dòng)作:*Implementationof{returnarray('user_block_user_action'=>array('description'=>t('Blockcurrentuser'),'type'=>'user','hooks'=>array(),'user_block_ip_action'=>'description'=>t('BanIPaddressofcurrent'type'=>'user','hooks'=>array(),}任何鉤子。如果我們能只改一下hooks鍵,那不就可以了?不錯(cuò),可以這樣做,讓我們往下看。使用drupal_alter()修改已有的Implementationofhook_drupal_alter().CalledbyDrupalhook_action_info()somodulesmaymodifytheaction_info@paramarrayTheresultofcallinghook_action_info()onall//Makethe"Blockcurrentuser"actionavailableto//commentinserttrigger.Ifothermoduleshavemodified//arrayalready,wedon'tstompontheirchanges;wejustmake//the'insert'operationispresent.Otherwise,weassign//'insert'if}else}}圖3-5.將動(dòng)作“當(dāng)前用戶(hù)”分配給評(píng)論插入觸發(fā)建立上下執(zhí)行該動(dòng)作了,它符合標(biāo)準(zhǔn)的動(dòng)作函數(shù)簽名example_action($object,$context)。載用戶(hù)動(dòng)作所需的$user對(duì)象。下面是來(lái)自modules/trigger/trigger.module的代碼,它給出了這是如何實(shí)現(xiàn)的:Whenanactioniscalledinacontextthatdoesnotmatchitstheobjectthattheactionexpectsmustberetrieved.Forexample,anactionthatworksonnodesiscalledduringthecommenthook,nodeobjectisnotavailablesincethecommenthookdoesn'tpassSohereweloadtheobjecttheaction@paramThetypeofactionthatisabouttobe@paramThecommentthatwaspassedviathecommentTheobjectexpectedbytheactionthatisabouttobefunction ment_context($type,{switch($type)//Anactionthatworkswithnodesisbeingcalledinacommentcontext.case'node':return//Anactionthatworksonusersisbeingcalledinacommentcontext.case'user':returnuser_load(array('uid'=>}}當(dāng)為我們的用戶(hù)動(dòng)作執(zhí)行前面的代碼時(shí),匹配的是第2種情況,所以將會(huì)加載用戶(hù)對(duì)象并接著執(zhí)行我們的用戶(hù)鉤子。評(píng) 首在對(duì)象中查找,其次在上下文中查找,最后使用全局變量ImplementationofaDrupalBlocksthecurrentfunctionuser_block_user_action(&$object,$context={if(isset($object->uid))$uid=$object-}elseif(isset($context['uid']))$uid=}elseglobal$uid=$user-}db_query("UPDATE{users}SETstatus=0WHEREuid=%d",$uid);watchdog('action','Blockeduser%name.',array('%name'=>}的。觸發(fā)器模塊總是將當(dāng)前的鉤子和操作放在上下文中,通過(guò)上下文將其傳遞過(guò)來(lái)。它們的值在$context['hook']檢查上下system,它可以被分配給許多不同的觸發(fā)器。動(dòng)作發(fā)送電子郵件在合成電子郵件期間,允許將特定的令牌替換掉。例如,你可能想在郵件的正文中包含一個(gè)節(jié)點(diǎn)的oesstemstmmoe中的動(dòng)作ImplementationofaconfigurableDrupalaction.Sendsane-{global{case//Becausethisisnotanactionoftype'node'(it'san//oftype'system')thenodewillnotbepassedas//butitwillstillbeavailableincase//Thecommenthookprovidesnid,in$comment=case'user'://Becausethisisnotanactionoftype'user'the//objectisnotpassedas$object,butitwillstill//availableinif(isset($context['node'])){$node=}elseif($context['recipient']=='%author')//Ifwedon'thaveanode,wedon'thaveanodeauthor.watchdog('error','Cannotuse%authortokeninthiscontext.');}//Wearebeingcalled$node=}動(dòng)作么動(dòng)作“嘟嘟多次”就需要知道嘟嘟的次數(shù)了。而其它的高級(jí)動(dòng)作,比如動(dòng)作“發(fā)送電子郵件”,可能需要的信息:電子郵type:'system'description:aid:type:callback:parameters:(serializedarraycontainingthebeepsparameterwithitsvalue,i.e.,thenumberoftimestobeep)description:Beepthree所以,在我們的動(dòng)作“嘟嘟多次”beep_multiple_beep_action()中通過(guò)$context['beeps就可以取得嘟嘟數(shù)字動(dòng)作ID(存放在數(shù)據(jù)庫(kù)表actions_aid中的)。直接使用actions_do()來(lái)調(diào)用一個(gè)動(dòng)的話(huà),那么推薦使用actions_do()來(lái)調(diào)用動(dòng)作。函數(shù)的簽名如下:actions_do($action_ids,&$object,$context=array(),$a1=NULL,$a2=:下面是我們?nèi)绾问褂胊ctions_do()來(lái)調(diào)用我們的簡(jiǎn)單動(dòng)作“嘟嘟”的:$object=NULL;//$objectisarequiredparameterbutunusedinthiscaseactions_do('beep_beep_action',$object);$object=NULL;$object=$context['beeps']=PHP開(kāi)發(fā)者可能會(huì)疑惑,“有必要使用動(dòng)作么?為什么不直接調(diào)用該函數(shù),或者僅僅實(shí)現(xiàn)一個(gè)鉤子?為什PHP參數(shù)不也能實(shí)現(xiàn)嗎?”答案是,通過(guò)編寫(xiě)一個(gè)帶有非常一般的函數(shù)簽名使用hook_hook_info()定義你自己的觸發(fā)實(shí)現(xiàn)的鉤子。例如,這里是來(lái)自comment.module的hook_hook_info()實(shí)現(xiàn)。定義觸發(fā)器描述的地方就是*Implementationof{returnarray('comment'=>array('comment'=>'insert'=>'runswhen'=>t('Aftersavinganew'update'=>'runswhen'=>t('Aftersavinganupdated'delete'=>'runswhen'=>t('Afterdeletinga'view'=>'runswhen'=>t('Whenacommentisbeingviewedbyanauthenticateduser')} *Implementationof{returnarray('monitoring'=>array('monitoring'=>array('overheating'=>array('runswhen'=>t('Whenhardwareisabouttomelt zing'=>'runswhen'=>t('Whenhardwareisabouttoze}module_invoke_all('monitoring','overheating')。它接著需要實(shí)hook_monitoring($op,并使用actions_do()modules/trigger/trigger.moduletrigger_cron()。圖3-6.新定義的觸發(fā)器以一個(gè)的形式顯示在了觸發(fā)器用戶(hù)界模塊定義了鉤子。如果它還定義了一個(gè)不同的鉤子,那么該鉤子既不會(huì)出現(xiàn)在下,也不會(huì)獨(dú)自擁有一個(gè)簽。然而,對(duì)于那些與模塊名字不匹配的鉤子,仍然可以使用路徑向已有鉤子中添加觸*Declareanewtrigger,toappearinthenodefunctionarchiveoffline_hook_info()$info['archiveoffline']=array('nodeapi'=>array('archive'=>'runswhen'=>t('Whenthepostisabouttobereturn}導(dǎo)航到觸發(fā)器管理頁(yè)面“管理??觸發(fā)器”3-7圖3-7.額外的觸發(fā)器(“當(dāng)文章即將被存檔”)Drupal的菜單系統(tǒng)將使用hook_hook_info()實(shí)現(xiàn)中的第一個(gè)鍵,來(lái)自動(dòng)在觸發(fā)器管理頁(yè)面創(chuàng)建一個(gè)。Drupal將我們可以使用hook__alter()來(lái)刪除不想要的(該鉤子的詳細(xì),可參看第4章)。下面的代碼將自動(dòng)創(chuàng)建,從類(lèi)型_LOCAL_TASK(Drupal默認(rèn)將其作為顯示)改為了類(lèi)型_CALLBACK,這樣Drupal就*Implementationof function _alter(&$items) } 總4Drupal菜單統(tǒng)看作一個(gè)擁有3種主要功能的系統(tǒng):1回調(diào)映射,2控制,3菜單定制菜單系統(tǒng)的基本代碼位于includes/.inc中,而可選代碼則位于modules/,后者可用來(lái)啟用菜單的一些特性比如自定義菜單等等.在本章中,探索一下什么是回調(diào)映射以及它是如何工作的,看一下如何通過(guò)控制來(lái)保護(hù)菜單項(xiàng),學(xué)習(xí)如何樣你就可以隨心所欲的定制Drupal了。回調(diào)映個(gè)b向Dpl向Dal個(gè)URLDpal必須要運(yùn)行哪段代碼以及如何處理這一請(qǐng)求。這也就是通常所說(shuō)的路由或者分發(fā)。Dal掉URL被為al路徑果URL是 /qo3則al路徑為od3如你了Dal潔UL的URL是 3的b服務(wù)器在Dal個(gè)UL以前,b為 ?o3于Dl潔URL其Dual是o,章Web服務(wù)器的角色。URL映射為為鍵,里面還包含了路徑的一些相關(guān)信息。一個(gè)模塊必須提供的一段信息就是頁(yè)面回調(diào)(pagecallback)。在這里,回調(diào) /?q=about來(lái)代替 Drupal將會(huì)使用node/3作為內(nèi)部路徑。該流程的圖示可參看圖4-1和4-2。圖4-1.圖4-2.菜單路由器和的構(gòu)建流程概創(chuàng)建一個(gè)菜單 ;name description=Learningaboutthe package=ProDrupalDevelopmentcore=接著我們創(chuàng)建 //UsethismoduletolearnaboutDrupal'sImplementationofhook_functionfun_()$items['fun']='pagecallback'=>'fun_o','accesscallback'=>TRUE,'type'=>return}Page{returnt('}在“管理?站點(diǎn)構(gòu)建?模塊”中,啟用該模塊,這樣就會(huì)將該菜單項(xiàng)插入到_router表中,這樣,當(dāng)我Drupal路徑。我們使用該路徑作為$itemsURL圖4-3.菜單項(xiàng)使得Drupal能夠找到和運(yùn) o()函數(shù)定義一個(gè)前面所寫(xiě)的 () fun']='title'=>'pagecallback'=>' 'accesscallback'=>TRUE,'type' return}們定義的標(biāo)題。為什么呢?這是因?yàn)镈rupal將所有的菜單項(xiàng)在了_router表中,盡管這里我們的代碼改動(dòng)了,Drupal來(lái)重新構(gòu)建_router表。這里有兩種方式。最簡(jiǎn)單的就是安裝開(kāi)發(fā)者模塊(),并在“管理?站點(diǎn)構(gòu)建?區(qū)塊”中啟用devel區(qū)塊。devel區(qū)塊中包含了一個(gè)名為重構(gòu)菜單的選項(xiàng)。點(diǎn)擊它將會(huì)重構(gòu)_router表。如果你沒(méi)有安裝開(kāi)發(fā)者模塊的話(huà),直接“管理?站點(diǎn)構(gòu)建?模塊”,也能實(shí)現(xiàn)同樣的效果。作為顯示該頁(yè)面的準(zhǔn)備工作的一部分,Drupal重構(gòu)了菜單表。從現(xiàn)在起,我假定大家知道知道圖4-4.頁(yè)面回調(diào)有時(shí),你可能希望向映射到該路徑上的函數(shù)提供的信息。首先,路徑中的其它部分將會(huì)自動(dòng)傳遞過(guò)來(lái)。讓我們修改一下 fun_o($first_name='',$last_name={return o@first_namearray('@first_name'=>$first_name,'@last_name'=>} /?q=fun/John/Doe,得到如圖4-5所示的輸出。圖4-5. ()$items['fun']array('title'=>'pagecallback'=> 'pagearguments'=>array('Jane','accesscallback'=>TRUE,'type'=>_CALLBACK,return}才是從路徑中生成的參數(shù)。來(lái)自URL的參數(shù)仍然可用;為了它們,你可以修改回調(diào)函數(shù)的簽名,從而添加來(lái)自于URLfunctionfun_o($first_name='',$last_name='',$a='',$b='')讓我們做一下測(cè)試,將JaneDoe放到頁(yè)面參數(shù)中,把JohnDoe放在URL中,然后看看結(jié)果。圖4-6.放在其它文件中的頁(yè)面回Drupal會(huì)假定你把頁(yè)面回調(diào)放在了.module文件中。在Drupal6中,對(duì)于每個(gè)頁(yè)面請(qǐng)求,為了盡可能的降低為其加載的代碼總量,許多模塊被拆分成了多個(gè)部分。如果回調(diào)函數(shù)不在當(dāng)前的.module文件中的話(huà),可以使用菜單項(xiàng)中的file鍵,來(lái)指定哪個(gè)文件包含了該函數(shù)。我們?cè)诘?章中編寫(xiě)注釋模塊的時(shí)候,就用到了file鍵。如果你定義了fileDrupal將會(huì)在你的模塊下查找該文件。如果你的頁(yè)面回調(diào)是由其它模Drupal在查找該文件時(shí)所用的文件路向?qū)Ш絽^(qū)塊中添加一 簡(jiǎn)單的映射到一個(gè)回調(diào)函數(shù)上了,而是讓Drupal把它作為一個(gè)菜單包含進(jìn)來(lái)。提示因?yàn)? () fun']array('title'=>'pagecallback'=>' 'pagearguments'=>array('Jane','Doe'),'accesscallback'=>TRUE,'type' return}圖4-7.Ifwedon?tlikewhereitisced,wecanmoveitdownbyincreasingitsweight.Weightisanotherkeyintheitemdefinition: () fun']array('title'=>'pagecallback'=>' 'pagearguments'=>array('Jane','Doe'),'accesscallback'=>'weight'=>return}TheeffectofourweightincreaseisshowninFigure4-8.itemscanalsoberelocatedwithoutchangingcodebyusingtheadministrationtools,locatedatAdminister?Sitebuildings(themodulemustbeenabledforthesetoolstoappear).圖4-8.菜單嵌functionfun_() fun']array('title'=>'pagecallback'=>' 'accesscallback'=>TRUE,'weight'=>- array('title'=>'Farewell','pagecallback'=>' 'accesscallback'=>TRUE,return}*Page {returnt('}*Page {return}Drupal2個(gè)菜單項(xiàng)(fun/farewell)的路徑是第一個(gè)菜單項(xiàng)路徑(fun)的孩子。因此,在顯示菜單時(shí)(轉(zhuǎn)化為HTML),Drupal將會(huì)縮進(jìn)第2個(gè)菜單項(xiàng),如圖4-9所示。它還在頁(yè)面的頂部正確的設(shè)置了面包屑,以指示嵌套關(guān)系。當(dāng)然,根據(jù)設(shè)計(jì)者的要求,可將菜單或面包屑顯示成所要的樣式。4-9.嵌套控可以我們的菜單。一般情況下,通過(guò)在模塊中使用hook_perm()來(lái)定義權(quán)限,并使用一個(gè)函數(shù)來(lái)測(cè)試這些權(quán)限,從而義一個(gè)名為receivegreeting的權(quán)限;如果用戶(hù)沒(méi)有哪個(gè)角色具有該權(quán)限的話(huà),當(dāng)他/她頁(yè)面/?q=fun時(shí),將會(huì)收到一個(gè)“”消息*Implementationof fun_perm(){}*Implementationof () fun']array('title'=>'pagecallback'=> 'accesscallback'=>'accessarguments'=>array('receive'weight'=>- array('title'=>'pagecallback'=> return}面的代碼中,是根據(jù)user_access('receivegreeting')的返回結(jié)果來(lái)判定是否允許的。這樣,菜單系統(tǒng)就相提示user_access()函數(shù)是默認(rèn)的回調(diào)。如果你沒(méi)有定義回調(diào)的話(huà),那么參數(shù)將被菜單系統(tǒng)傳遞子菜單一般不會(huì)繼承父菜單項(xiàng)的回調(diào)和參數(shù)。所以必須為每個(gè)菜單項(xiàng)定義accessarguments鍵。如果回調(diào)不是user_accessaccesscallback標(biāo)題的本地化和定'title'=>t('Greeting')//No!don'tuset() itemtitlesor然而,你想錯(cuò)了。菜單字符串是以原始字符串的形式在_router表中的,而菜單項(xiàng)的翻譯則被推了運(yùn)行時(shí)進(jìn)行。真實(shí)情況是,Drupal有一個(gè)默認(rèn)的翻譯函數(shù)(t()函數(shù)),它被指定用來(lái)翻譯菜單標(biāo)題。你將在后面看到,如何將默認(rèn)翻譯函數(shù)修改為你選擇的函數(shù),以及如何向該函數(shù)傳遞參數(shù)。負(fù)責(zé)翻譯的函數(shù)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論