![專業(yè)開發(fā)指南drupal6中文版_第1頁](http://file4.renrendoc.com/view/bd2cab5c0e59d28da0270f836531d4f0/bd2cab5c0e59d28da0270f836531d4f01.gif)
![專業(yè)開發(fā)指南drupal6中文版_第2頁](http://file4.renrendoc.com/view/bd2cab5c0e59d28da0270f836531d4f0/bd2cab5c0e59d28da0270f836531d4f02.gif)
![專業(yè)開發(fā)指南drupal6中文版_第3頁](http://file4.renrendoc.com/view/bd2cab5c0e59d28da0270f836531d4f0/bd2cab5c0e59d28da0270f836531d4f03.gif)
![專業(yè)開發(fā)指南drupal6中文版_第4頁](http://file4.renrendoc.com/view/bd2cab5c0e59d28da0270f836531d4f0/bd2cab5c0e59d28da0270f836531d4f04.gif)
![專業(yè)開發(fā)指南drupal6中文版_第5頁](http://file4.renrendoc.com/view/bd2cab5c0e59d28da0270f836531d4f0/bd2cab5c0e59d28da0270f836531d4f05.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
總1Drupal23,動作,4Drupal5Drupal6Drupal7Drupal第8章系9Drupal1213Drupal14151619XML-20序在一年多以前,我為本書的第一版寫了序言。那時,在Drupal世界里缺少的就是一本開發(fā)。通過編寫本書的第一版,有一本第一版的Drupal專業(yè)開發(fā)指南。Drupal,通過它的開源本性,已經(jīng)成為了一個偉大的軟件,這比我預期的要好很多。Drupal開發(fā)者社區(qū)勇于創(chuàng)新,同時以極大的熱情擁抱web開發(fā)的每個技術(shù),并努力為web開發(fā)者提供近乎無限的可能性。在Drupal社區(qū)中,變是永過700多的開發(fā)者為Drupal6的代碼貢獻了力量。通過共同努力,我們對系統(tǒng)作了重要改進,對多語言提供API、JavaScriptDrupal5相比,Drupal6是一個更優(yōu)秀的web應(yīng)用開發(fā)平臺。開發(fā)者。所以,如果對于Drupal6還缺少什么的話,那么它就是本書了,我非常感謝John修訂并擴展了本書。們,我們專注于Drupal的穩(wěn)定、靈活、強大。我非常樂意去評估和提交你的Drupal補丁,我敢肯定其他的DriesDrupal關(guān)于作JOHNVANDYKBell&HowellAppleIILittleBrickOut,打印和檢查BASIC代碼,以增加paddle寬度。在發(fā)現(xiàn)Drupal以前,John參與了UserLandFrontier社區(qū),并Ruby編寫了自己的內(nèi)容管理系統(tǒng)(和MattWestgate)。John是一web架構(gòu)師,效力Lullabot,一個著名的Drupal教育和咨詢公司。在此以前,JohnIowa州立科技大學的昆蟲系工作,他是一名系統(tǒng)分析員和助理教授。他的是關(guān)于鹿鳴的耐寒性的,他的博士關(guān)于正在研究的使用相片來創(chuàng)建3維虛擬昆蟲。技術(shù)審稿ROBERTDOUGLASS的Drupal探索始于2003年,他創(chuàng)建了自己的個人RobsH。在2005年,他與人合著了使用Drupal,phpBB,和WordPress構(gòu)建社區(qū)。作為第一本深度講解Drupal的書籍,它為Drupal的初學者DrupalDrupal致這包括,BrandonBergren,?ivindBinde,Larry“Crell”Garfield,DmitriGaskin,Gordon,GerhardKillesreiter,GregKnaddison,Druplicon,RobLoach,ChadPhillips,OlegTerenchuck.。對于那些做出貢獻而在RobertDouglassKárolyNégyesiAddisonBerryAngelaByron,HeineDeelstra,JeffEaton,NathanHaug,KevinHemenway,GáborHojtsy,BarryJaspan,Earl,和JamesWalker認真的檢查了本書的全部或部分手稿,感謝Apress小組在示例代碼需要不斷修改時的和理解,以及魔術(shù)般的將我的手稿轉(zhuǎn)變?yōu)榱艘槐緯н@就是我們的經(jīng)歷,你可能也會遇到類似的情況。旅程的終點讓人感到欣慰——成千上萬的開發(fā)者在為同一個項3種讀者。首先,這里有大量的插圖,包括各種圖表和流程圖;還有許多內(nèi)容Drupal是什樣你很快就會熟悉Drupal了。最后,本書包含了大量的評論、提示、還有對代碼的詳細解釋,這將整本書有機的聯(lián)系到了一起。這適用于想成為Drupal高手的人。最后,你可以從htt 到本書的示例代碼,流程圖和。祝您好運并歡迎來到Drupal社區(qū)!中文版說 版方的,翻譯文檔學習參考使用,私自或用于商業(yè)目的。由此造成的任何糾紛和本人概不負責。第一Drupal的工作原在本章中,為你展示Drupal的概貌。會在以后章節(jié)中,對Drupal中的每個部分的工作原理進行詳細的介紹。在這里,討論Drupal運行所用到的技術(shù)堆棧,Drupal包含的各種文件,和Drupal使用的各種不同的概念術(shù)語,比如節(jié)點,鉤子,區(qū)塊和。什么是Drupal是用來構(gòu)建的。它是一個高度模塊化,開源的web內(nèi)容管理框架,并且非常注重合作,互動的重要性。它的特點包括可擴展性強,符合標準,追求簡潔代碼,內(nèi)核精練。Drupal自帶了一些基本的功能,其它的額外功能可通模塊來完成的,而不是修改組件中的代碼。它還將內(nèi)容管理和內(nèi)容表示這二者進行了成功的分離。個報紙;一個圖庫;一個內(nèi)部網(wǎng),Drupal的應(yīng)用非常廣泛,這里僅僅提到了其中的一部分。它甚至可用于教育。著Drupal系統(tǒng);可參看和。技術(shù)堆使用最流行的技術(shù),而后者則意味著嚴謹?shù)木幋a。Drupal的技術(shù)堆棧如圖1-1所示。操作系統(tǒng)位于技術(shù)堆棧的最底層,Drupal基本不用關(guān)心底層的操作系統(tǒng)。只要它支持PHP,就可以運行Drupal。的這種長期的友Drupal的根下自帶了一個.htaccess,用來確Drupal安裝的安全以使Apache的mod_rewrite模塊來實現(xiàn)簡潔(Clean)URLs將URL中的“?”,“&”以及其它奇怪的符號清除掉,在Drupal中去掉的是“?q=”。這一點特別重要,當從其它的內(nèi)容管理系統(tǒng)或者靜態(tài)文件中遷移到Drupal上時,依照TimBerners-LeeMySQL和PostgreSQL,不過對 SQL和Oracle的支持也在不斷增加。影響。然而,PHP也可以用于構(gòu)建嚴謹?shù)拇a。Drupal中的所有代碼都遵守了嚴格的編碼規(guī)范PHP的門檻比較低,這就意味著有的人能夠為Drupal貢獻代碼,通過開源,會有很多人對這些Drupal的是由一個輕量級的框架構(gòu)成的。當你從Drupal時,得到的就是Drupal。它負責提供用戶管理、分類、和模板,如圖1-2所示。圖1-2Drupal內(nèi)核的概貌(沒有展示完所有的功能管理界面(rt efc)Drupal的管理界面與站點的前臺部分緊密的集成在了一起,并且在默認情況下,使用相同的。第用戶區(qū)塊(參看“區(qū)塊”部分)中看到管理站點的一個。點擊這一,你將進入到Drupal的管理界面。根據(jù)用戶對站點權(quán)限的不同,每個用戶的區(qū)塊都會有一個不同的。模塊DrupalDrupal3方模塊,編寫自己的模塊。這樣,就可以根據(jù)1-3所示。圖1-3通過啟用其它模塊來添加的功鉤子塊名”+“鉤子名”——comment_user()locale_user(),節(jié)點模塊中塊系統(tǒng)(Drupal鉤子)”。的模板方式,比如Smarty,PHP模板屬性語言(PHPTAL),和PHPTemte。在Drupal中可以使用多種方式來為你的定制外觀。最簡單的方式是使用CSS來覆蓋Drupal內(nèi)置的類和ID然而,HTML輸出時,你會發(fā)現(xiàn)很容易就可以實現(xiàn)你的目標。Drupal的模板文件由標準的HTML和PHP組成。另外,Drupal頁面的每個動態(tài)部分(比如盒子、列表、或者面包屑),都可以通過一個具有合適名字的函數(shù)進行覆寫。接著,Drupal將使用你的函數(shù)來創(chuàng)建頁面的該部分。節(jié)點區(qū)塊(區(qū)塊是在你模板的特定位置上,可以啟用或者禁用的信息。例如,一個區(qū)塊可以用來顯示你站點當前用戶的人數(shù)。文件布局( 通過了解Drupal默認安裝的 的Drupal安裝輪廓。一個Drupal默認安裝的 結(jié)構(gòu)如圖1-4所示。 )下面的任何東西,你要添加的其它模塊須放到sites 安裝成為一個電子商務(wù)平臺。scripts:包含了許多,這些可用于語法檢查,代碼清潔,從命令行運行Drupal,使用cron處理特定情況等等。在Drupal的請求生命周期中,用不到它;里面包含一些s和Perl的實用sites:包含了你對Drupal所進行的修改,包括設(shè)置、模塊、等形式(參看圖1-5)。你從第3方模塊庫中的模塊,或者你自己編寫的模塊,都放在sites/all/modules下面。這使得你對Drupal所進行的任何修改都保存在單個文件夾里。在sites下面有一個名為default的子,里面包含了你的Drupal站點的默認的設(shè)置文件default.settings.php。會拷貝默認,并將其重命名為你站點的URL,所以你最終的設(shè)置文件就位于 web服務(wù)器需要具有對這個子進行讀和寫的權(quán)限。如果可以的話,Drupal的安裝器將會為你自動的創(chuàng)建這個子,并update.phpDrupal版本升級后,用來更新數(shù)據(jù)庫模式(schema)服務(wù)一個請求( 當Drupal收到一個請求時都發(fā)生了什么呢?如果對此能有一個概括性的了解,那么對以后的學習將會很有幫助,所以本部Web服務(wù)器的角色(TheWebServer’sPHP設(shè)置,并啟用簡潔URL。基本上對Drupal的所有調(diào)用都是從index.php開始的。例如,調(diào)用在我們的例子中,路經(jīng)就為foo/bar。 這一流程的結(jié)果就是,Drupal對 /foo/bar和 的處理方式是一樣的,因為對于Drupal來說,這兩者的內(nèi)部路徑是一樣的。這就使得Drupal可以使用不帶“?q=”的URL了。這些URL被稱為簡潔URL。在備選的web服務(wù)器中,比如微軟的IIS,可以使ISAPI模塊比如ISAPI_Rewrite來實現(xiàn)簡潔URL。IIS7及引導指令流程 or 引導指令流程(Theotsrp初始配置(ofuo)DrupalURL($base_url)include_once()來解析前期頁面緩存(ElPage文件則通過將cache_inc變量設(shè)置為文件的路徑來定義。具體示例可參看緩存一章。初始化數(shù)據(jù)庫(Initialize基于主機名/ID地址進行控制(Hostname/IP-BasedAccessControl)Drupal支持基于主機名/IP地址來主機(對站點的)。在控制階段,會快速的檢查請求是否來自一個被禁初始化會話處理(InitializeSession階段,將初始化或者重新構(gòu)建會話。代表當前用戶的全局對象$User也會在這一階段初始化,不過出去效率的原因,并不是對象的所有屬性都是可用的(當需要時,可以通過明確的調(diào)用函數(shù)user_load()來加載這些屬性)。后期頁面緩存(LatePage在后期頁面緩存階段,Drupal會加載足夠的支持代碼,來決定是否需要從頁面緩存中提供一個頁面。這包括,把來自于語言判定(Language路徑處理Drupal內(nèi)部路徑的緩存和查找操作。完成該階段是引導指令的最后一個階段,它包括加載一個通用函數(shù)庫,支持,和支持回調(diào)映射,文件處理,Unicode,PHPDrupal定制的錯誤處理器,并加載所有啟用了的模塊。最后Drupal調(diào)用init鉤子,這樣在對請求正式開始處理以前,將有機會通知相應(yīng)的模塊。Drupal整個引導指令完成以后,那么框架中的所有部分現(xiàn)在都可以使用了?,F(xiàn)在就可以獲得瀏覽器的請求并將它控制。模塊使用菜單鉤子來它們的回調(diào)函數(shù)(信息,參看第4章)處理一個請求(Processinga括,將從數(shù)據(jù)庫中取回該節(jié)點的數(shù)據(jù),并將它放到一個數(shù)組中。接著,就到了化的時候了?;瘮?shù)據(jù)(Themingthe選用的,來為網(wǎng)頁提供一個合適的外觀,并將生成的HTML返回給web瀏覽器。總結(jié)服務(wù)處理流程的各個部分,會在后面章節(jié)中作出詳細介紹。2建一個模塊在許多開源的應(yīng)用中,你可以通過修改源代碼來定制應(yīng)用。這是法,用來獲得你想要的功能;但是在drupal中,一般不贊成這樣做,只有在萬不得已的情況下才使用這一。修改源代碼,意味著隨著Drupal的每次更新,你必須要做的工作你必須測試一下你的修改是否還能正常工。代替的,Drupal的設(shè)計從底層便考慮了模塊化和擴展性。modules下面?,F(xiàn)在看一下這個子,然后導航到“管理??模塊”,比較一下子下的模塊與管理界面上在本章,從頭開始創(chuàng)建一個模塊;在你創(chuàng)建模塊時,你將學到模塊必須遵守的一些標準。我們管理員啟用了評論模塊,那么用戶可能會對內(nèi)容評論。但是如果是在一個網(wǎng)頁上添加一個注釋(一種 創(chuàng)建相應(yīng)的文置這個模塊。我們可以把這個模塊放在模塊所在的中去,不過這樣的話,我們需要記住哪些是模塊,哪些是我們的模塊,這樣一來,就增加了成本。讓我們把它放在sites/all/modules下面,以將其與模塊區(qū)分開來。sites/all/modules/custom下面創(chuàng)建一個名為annotate的。這樣就可以將你開發(fā)的自定義模塊與你的第3方模塊區(qū)分開了。如果有一天,你需要將你的委托給另一個開發(fā)者,那么這一點還是很有幫助的,不過是否將它;name=description=Allowsuserstoannotatenodes.core=6.xpackage=ProDrupal這個文件的格式非常簡單,在這里一個鍵對應(yīng)一個值。我們從版本管理系統(tǒng)(CVS)的標識開始。如果我們想和其他用戶這一模塊,通過將它提交到Drupal的第3方模塊中,這個值將會被CVS自動替換。接著,我們?yōu)镈rupal提供決定的;這樣,如果我們有3個不同的模塊,它們都有package=ProDrupalDevelopment,那么它們將被放在同一組中。PHP5.2,依賴于;name=Forumdescription=Randomlyreassignsrepliestodifferentdiscussionthreads.core=6.xdependencies[]=forumpackage="EvilBob'sForumBonusPak"php=5.2你可能會想,為什么我們需要一個單獨的.info文件呢?為什么不在我們的主模塊中寫一個函數(shù)來返回這些元數(shù)據(jù)呢?超出分配給PHP的內(nèi)存上限?,F(xiàn)在我們準備好創(chuàng)建一個實際的模塊了。在你的sites/all/modules/custom/annotate //LetsusersaddprivateannotationstoAddsatextfieldwhenanodeisdissothatauthenticatedusersmaymake描述。注意,我們在這里有意的不使用結(jié)束?>;這對于PHP來說是可選的,如果包含了它,就可能導致文件的尾部空格問題(參看)。注意為什么我們在這里這么詳細的講述每一個細節(jié)?這是因為,如果來自世界各地的成百上千的人開發(fā)同一個項目的話,DrupalDrupal開發(fā)用戶手實現(xiàn)一個含菜單項的數(shù)組。每一項(我們這里只有一項)都以路徑為鍵,在這里就是admin/settings/annotate。菜單項的值是一個數(shù)組,里面包含的鍵和值是用來描述在該路徑被請求時Drupal要做什么的。這方面的詳細,可參看第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}此時不要過于關(guān)注這里的具體細節(jié)。這段代碼說,“當用戶訪問頁面/?q=admin/settings/annotatedrupal_get_form并向它傳遞了一個表單otate_ad_eotatamc中查找描述該表單的函數(shù)。只有具有管理站點配置權(quán)限的用戶al(Dal數(shù)。現(xiàn)在你應(yīng)該清楚我們?yōu)槭裁窗阉凶鱤ook_()或者菜單鉤子了??梢酝ㄟ^在鉤子的名字前加上你的模塊名來創(chuàng)建Drupal鉤子。提示Drupal的鉤子幾乎允許你修改這個軟件的任何方面。你可以在Drupal的API文檔站點()上,找到Drupal鉤子的完整列表和它們的使用說明。添加特定于模塊的呈現(xiàn)一組復選框,每一個復選框就對應(yīng)一個已有的內(nèi)容類型。這樣終端用戶就可以通過選中或者取消選中復選框(21所示otatmoe文件里,而對于每個置表單,所以創(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}選框。我們在變量$options中已經(jīng)得到了帶鍵的數(shù)組。'page'=>'Page','story'=>一個名為“SavoryRecipe”的節(jié)點類型,那么數(shù)組看起來應(yīng)該這樣:'page'=>'Page','savory_recipe'=>'SavoryRecipe','story'=>因此,在我們web表單中,為節(jié)點類pagestory生成了相應(yīng)的復選框。我們通過定義屬性#title的值,為表單元素設(shè)置了一個標題。在多于一個的復選框),所以#default_value的值將會是一個數(shù)組。用來大量的數(shù)據(jù)。對于配置屬性這樣簡單數(shù)值的,它卻是一個非常方便的系統(tǒng)。注意我們傳遞給varialble_get()注釋的節(jié)點類型。在默認情況下,我們允許對節(jié)點類型page進行注釋。保存你剛創(chuàng)建的文件,然后導航到“管理??模塊”proDrupalDevelopment的組中,在模塊sites/all/modules/custom中)。繼續(xù)前進,啟用你的新模塊。圖2-1,annotate.module盡管代碼中的一行有點太長了,但是沒有關(guān)系,你現(xiàn)在應(yī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}}這個看起來有點復雜,所以讓我們詳細的分析一下。首先要注意的是,我們在這里實現(xiàn)了Drupal的另一個鉤子。這次是 在我們的代碼被調(diào)用時在Drupal中將發(fā)生什么。這些信息保存在了參數(shù)$op中,它可以是接下來,我們快速的檢查了一些我們不想顯示注釋字段的情況。一種情況是$user對象的用戶ID為0時,這意味著查看節(jié)點的用戶此時沒有登錄(global將$user對象包含了進來,這樣我們就可以測試當前用戶是否登錄了)。另一種情況是當參數(shù)$page不為TRUE時,我們想表單的顯示。如果它為FALSE,這意味著,這個節(jié)況下,我們不需要添加任何東西。我們使用break語句來跳出switch語句從而對頁面的修改。如果節(jié)點類型不是我們想要注釋的,使用break語句來跳出switch語句。將在annotate.module中的一個單獨的函數(shù)中完成這件事,它唯一的責任就是定義表單: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)建表單的方式,和我們在函數(shù)annotate_admin_settings()中使用的一樣,都是創(chuàng)建一個鍵值數(shù)組 頁面的下面,所以我們?yōu)樗峙淞艘粋€相對較大的重量10.我們要顯示的是我們的表單,所以我們調(diào)用函數(shù)2-2drupalweb把數(shù)據(jù)到數(shù)據(jù)庫表模塊所用數(shù)據(jù)的最常用方式,就是為這個模塊的數(shù)據(jù)創(chuàng)建一個單獨的數(shù)據(jù)庫表。這將使得該數(shù)據(jù)與drupal數(shù)據(jù)庫SQL語句如下所示:CREATETABLE(uidint(10)NOTNULL,nidint(10)NOTNULL,notelongtextNOTNULL,whenint(11)NOTNULLdefault'0',PRIMARYKEY(uid,nid),則使用.install,所以對于annotate.module,這個文件名應(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}在第一次啟用注釋模塊時,drupal會查找文件annotate.install并運行函數(shù)annotate_install(),它將我們在模式鉤DrupalDrupal將它們轉(zhuǎn)化為了我們當前所用數(shù)據(jù)站點構(gòu)建如果前面的辦法無效的話,那么還有最后的,那就是在數(shù)據(jù)庫的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}以無縫的實現(xiàn)數(shù)據(jù)庫表的前綴化(關(guān)于表前綴化的詳細,可參看文件sites/default/settings.php中的注釋)。第三,在用戶的會話中,在用戶查看的下一個頁面時,它就會被Drupal作為一個通知顯示給用戶。這樣,用戶就獲得一些反饋信我們的表單。在我們把我們的表單分配給$node->content的代碼前面,我們添加以下代碼,這里用粗體將其標出了: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專業(yè)開發(fā)者的道,你已經(jīng)邁出了關(guān)鍵的一步。定義你自己的管理么你可以非常容易的創(chuàng)建一個。在這個例子中,我們創(chuàng)建一個名為“Nodeannotation”的新類別。為了實現(xià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)在作為一個單獨的類別出現(xiàn)有多種方式:可以直接清空cache_表,或者使用Drupal的開發(fā)模塊(devel.module)所提供的“重構(gòu)菜單”,或者導航到“管理?站點配置?性能”并點擊“清除緩存數(shù)據(jù)”按鈕。sites/all/modules/devel,接著啟用該模塊,然后導航到“管理??區(qū)塊”,啟用它的開發(fā)區(qū)塊。路徑(admin/annotate)。我們:它應(yīng)該放在右欄中,重量為-5,這樣它就恰好位于“站點配置”類別的上面,從而方便了截圖,如圖2-3所示的。第二步是告訴Drupal,把指向注釋設(shè)置的實際放在類別“Nodeannotation”的內(nèi)部。我們通過修改原有菜單項的單項是“站點配置”類別路徑admin/settings的孩子,如表2-1所示。當Drupal重新構(gòu)造菜單樹時,它查找路徑來為父菜單菜單項建立繼承關(guān)系,由于admin/annotate/settings是admin/annotate的孩子,這決定了要像圖2-3那樣顯示。將模塊菜單項嵌套在如表2-1所示的任意一個路徑下,將使模塊出現(xiàn)在Drupal管理頁面中該類別的下面。2-1路 類 /?q=admin/annotate/settings時,調(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驗證用戶提交的設(shè)Validatetheannotationconfigurationif(!is_numeric($limit)){form_set_error('annotate_limit_per_node',t('Pleaseentera}}入了無效數(shù)據(jù)的話,那么為發(fā)生錯誤的字段設(shè)置一個錯誤信息,這反映為在頁面上就是顯示一個警告信息,并將包含錯誤的字段進行顯示,如圖2-5所示:圖2-5驗證設(shè)置了一個錯誤信Drupal是怎么知道要調(diào)用我們的函數(shù)呢?我們對函數(shù)名采用了特殊的方式,使用表單定義函數(shù)的名設(shè)DrupalvariablesDrupal在數(shù)據(jù)庫中有一個名為variables的表,并且鍵-值對可以使用variable_set($key,$value)來,使用annotate_limit_per_node)的名字相同。命名方式為:你的模塊名加上一個描述性的名稱。表單字段和變量的鍵應(yīng)該由于Annotationswillbedeleted”字段是一個單選按鈕,所以它看起來復雜了一點。這個字段的#option'#options'=>)'#options'=>[0]=>[1]=>[2]=>t('After30)=>',)//使用variable_get()來取回的//Getstoredsetting umnumberofannotationsper$max=variable_get('annotate_limit_per_node',篇外與開源社區(qū)這一模塊,這是自然的,所以需要創(chuàng)建一個README.txt文件,然后把它放到annotation的 可,而上的打包將會為模塊自動添加一個LICENSE.txt文本。接下來,你就可以把它上傳到上的第3方模塊中了,然后創(chuàng)建一個項目頁面,用來追蹤社區(qū)中其他用戶的反饋??傁l(fā)布以后收到一封電子郵件?;蛘弋斢脩粼谠u論中使用了詞語,那么就會被自動封號。本章將描Drupal的鉤子,從而當那些發(fā)生時,能夠運行自己的代碼。使用使用理解和觸發(fā)理流程進行交互。表3-1給出了一些Drupal。類型創(chuàng)建一個節(jié) 節(jié)刪除一個節(jié) 節(jié)查看一個節(jié) 節(jié)創(chuàng)建一個用戶帳 用更新用戶用 登 用Drupal開發(fā)者將這些內(nèi)部稱為鉤子,這是因為當一個發(fā)生時,Drupal允許模塊從該點鉤進Drupal的執(zhí)行路徑。 判定對哪個Drupal做出文件,并將其放在了sites/all/modules/custom/beep/:;name=description=Simulatesasystembeep.package=ProDrupalDevelopmentcore=6.x//Provideasimulatedfunctionbeep_beep()}錄時發(fā)出嘟嘟聲。通過在我們的模塊中實現(xiàn)hook_user(),并將邏輯添加到login操作中,我們就可以完成目標了:Implementationoffunctionbeep_user($op,&$edit,&$account,$category={if($op=='login'){}}Implementationoffunctionhook_nodeapi(&$node,$op,$a3=NULL,$a4={if($op=='insert'){}}如果我們想在添加評論時,也讓Drupal發(fā)出嘟嘟聲,那又該怎么辦呢?好的,我們可以實現(xiàn) 如“用戶鉤子,登錄操作”或者“nodeapi鉤子,插入操作”。當這些操作發(fā)生時,trigger.module就會讓你觸發(fā)一個動作。理解動一個動作就是Drupal要做的一些事情。下面是一些例PHP函數(shù)有觸發(fā)器用戶界導航到“管理??模塊”,并啟用觸發(fā)器模塊。接著導航到“管理??觸發(fā)器”圖3-1.不是所有的動作對所有的觸發(fā)器都可用,這是因為有些動作在特定的上下文中沒有任何意義。例如,在觸發(fā)器“在刪除表3-2.Drupal6鉤 操 觸發(fā)器名 在刪除評論后 cron 在用戶帳戶創(chuàng)建之后 userview你的第一個動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ù)的名字為是個動作,我們在我們的beep_beep()函數(shù)的名字后面追加了_actionbeep_beep_action()。type:這是你編寫的動作的類型。Drupal使用該信息,將動作歸類到觸發(fā)器分配界面的下拉選擇框中??赡艿念愋桶ㄊ裁磳ο竽??”(如果答案不確定,或者是“各種不同的對象!”,那么可以使用system類型)。hooks:在這個鉤子數(shù)組中,每個條目都是用來列舉該動作所支持的操作的。Drupal使用這一信息,來判定該動作在觸發(fā)Simulateabeep.ADrupal{}分配該動個用戶界面,如圖3-2所示。圖3-2.修改動作所支持的觸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}高級動嘟嘟一下,這就完事了。但是許多時候,動作可能需要一點的上下文。例如,一個“發(fā)送電子郵件”動作,需要知道將電如果你想告訴Drupal你的動作是一個高級動作的話,你需要進行以下步驟:在你模塊的hook_action_info()實現(xiàn)中將配置表單。表3-3對簡單動作和高級動作的區(qū)別進行了總結(jié)。簡單動無高級動無 *如果需要的話,可以使用$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,所以按照約定,我們在后面追加提交函數(shù)的名字為:動作*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)}擇添加一個高級動作“嘟嘟多次”時,如圖3-3所示,Drupal將會使用我們的表單字呈現(xiàn)一個完整的動作配置表單,如圖3-4所示。圖3-4.動作“嘟嘟多次”嘟五次并將其描述為“嘟嘟五次”。這樣,在將動作分配給一個觸發(fā)器時,我們就了這兩個高級動作之間的區(qū)別。這樣,提示
*Configurableaction.Beepsaspecifiednumberof{for($i=1;$i<$context['beeps'];$i++){}}我們需要了解當前的上下文信息,那么可以簡單的將我們的簡單動作的函數(shù)簽名從beep_beep_action()改為beep_beep_action($object,$context)。所有的動作都可以使用$object和$context參數(shù)。在動作中使用上下::觸發(fā)器模塊是如何準備上下文user.module,我們看到Drupal已經(jī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鍵,那不就可以了?不錯,可以這樣做,讓我們往下看。使用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.將動作“當前用戶”分配給評論插入觸發(fā)建立上下執(zhí)行該動作了,它符合標準的動作函數(shù)簽名example_action($object,$context)。載用戶動作所需的$user對象。下面是來自modules/trigger/trigger.module的代碼,它給出了這是如何實現(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'=>}}當為我們的用戶動作執(zhí)行前面的代碼時,匹配的是第2種情況,所以將會加載用戶對象并接著執(zhí)行我們的用戶鉤子。評 首在對象中查找,其次在上下文中查找,最后使用全局變量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ā)器模塊總是將當前的鉤子和操作放在上下文中,通過上下文將其傳遞過來。它們的值在$context['hook']檢查上下system,它可以被分配給許多不同的觸發(fā)器。動作發(fā)送電子郵件在合成電子郵件期間,允許將特定的令牌替換掉。例如,你可能想在郵件的正文中包含一個節(jié)點的oesstemstmmoe中的動作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=}動作么動作“嘟嘟多次”就需要知道嘟嘟的次數(shù)了。而其它的高級動作,比如動作“發(fā)送電子郵件”,可能需要的信息:電子郵type:'system'description:aid:type:callback:parameters:(serializedarraycontainingthebeepsparameterwithitsvalue,i.e.,thenumberoftimestobeep)description:Beepthree所以,在我們的動作“嘟嘟多次”beep_multiple_beep_action()中通過$context['beeps就可以取得嘟嘟數(shù)字動作ID(存放在數(shù)據(jù)庫表actions_aid中的)。直接使用actions_do()來調(diào)用一個動的話,那么推薦使用actions_do()來調(diào)用動作。函數(shù)的簽名如下:actions_do($action_ids,&$object,$context=array(),$a1=NULL,$a2=:下面是我們?nèi)绾问褂胊ctions_do()來調(diào)用我們的簡單動作“嘟嘟”的:$object=NULL;//$objectisarequiredparameterbutunusedinthiscaseactions_do('beep_beep_action',$object);$object=NULL;$object=$context['beeps']=PHP開發(fā)者可能會疑惑,“有必要使用動作么?為什么不直接調(diào)用該函數(shù),或者僅僅實現(xiàn)一個鉤子?為什PHP參數(shù)不也能實現(xiàn)嗎?”答案是,通過編寫一個帶有非常一般的函數(shù)簽名使用hook_hook_info()定義你自己的觸發(fā)實現(xiàn)的鉤子。例如,這里是來自comment.module的hook_hook_info()實現(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')。它接著需要實hook_monitoring($op,并使用actions_do()modules/trigger/trigger.moduletrigger_cron()。圖3-6.新定義的觸發(fā)器以一個的形式顯示在了觸發(fā)器用戶界模塊定義了鉤子。如果它還定義了一個不同的鉤子,那么該鉤子既不會出現(xiàn)在下,也不會獨自擁有一個簽。然而,對于那些與模塊名字不匹配的鉤子,仍然可以使用路徑向已有鉤子中添加觸*Declareanewtrigger,toappearinthenodefunctionarchiveoffline_hook_info()$info['archiveoffline']=array('nodeapi'=>array('archive'=>'runswhen'=>t('Whenthepostisabouttobereturn}導航到觸發(fā)器管理頁面“管理??觸發(fā)器”3-7圖3-7.額外的觸發(fā)器(“當文章即將被存檔”)Drupal的菜單系統(tǒng)將使用hook_hook_info()實現(xiàn)中的第一個鍵,來自動在觸發(fā)器管理頁面創(chuàng)建一個。Drupal將我們可以使用hook__alter()來刪除不想要的(該鉤子的詳細,可參看第4章)。下面的代碼將自動創(chuàng)建,從類型_LOCAL_TASK(Drupal默認將其作為顯示)改為了類型_CALLBACK,這樣Drupal就*Implementationof function _alter(&$items) } 總4Drupal菜單統(tǒng)看作一個擁有3種主要功能的系統(tǒng):1回調(diào)映射,2控制,3菜單定制菜單系統(tǒng)的基本代碼位于includes/.inc中,而可選代碼則位于modules/,后者可用來啟用菜單的一些特性比如自定義菜單等等.在本章中,探索一下什么是回調(diào)映射以及它是如何工作的,看一下如何通過控制來保護菜單項,學習如何樣你就可以隨心所欲的定制Drupal了。回調(diào)映個b向Dpl向Dal個URLDpal必須要運行哪段代碼以及如何處理這一請求。這也就是通常所說的路由或者分發(fā)。Dal掉URL被為al路徑果URL是 /qo3則al路徑為od3如你了Dal潔UL的URL是 3的b服務(wù)器在Dal個UL以前,b為 ?o3于Dl潔URL其Dual是o,章Web服務(wù)器的角色。URL映射為為鍵,里面還包含了路徑的一些相關(guān)信息。一個模塊必須提供的一段信息就是頁面回調(diào)(pagecallback)。在這里,回調(diào) /?q=about來代替 Drupal將會使用node/3作為內(nèi)部路徑。該流程的圖示可參看圖4-1和4-2。圖4-1.圖4-2.菜單路由器和的構(gòu)建流程概創(chuàng)建一個菜單 ;name description=Learningaboutthe package=ProDrupalDevelopmentcore=接著我們創(chuàng)建 //UsethismoduletolearnaboutDrupal'sImplementationofhook_functionfun_()$items['fun']='pagecallback'=>'fun_o','accesscallback'=>TRUE,'type'=>return}Page{returnt('}在“管理?站點構(gòu)建?模塊”中,啟用該模塊,這樣就會將該菜單項插入到_router表中,這樣,當我Drupal路徑。我們使用該路徑作為$itemsURL圖4-3.菜單項使得Drupal能夠找到和運 o()函數(shù)定義一個前面所寫的 () fun']='title'=>'pagecallback'=>' 'accesscallback'=>TRUE,'type' return}們定義的標題。為什么呢?這是因為Drupal將所有的菜單項在了_router表中,盡管這里我們的代碼改動了,Drupal來重新構(gòu)建_router表。這里有兩種方式。最簡單的就是安裝開發(fā)者模塊(),并在“管理?站點構(gòu)建?區(qū)塊”中啟用devel區(qū)塊。devel區(qū)塊中包含了一個名為重構(gòu)菜單的選項。點擊它將會重構(gòu)_router表。如果你沒有安裝開發(fā)者模塊的話,直接“管理?站點構(gòu)建?模塊”,也能實現(xiàn)同樣的效果。作為顯示該頁面的準備工作的一部分,Drupal重構(gòu)了菜單表。從現(xiàn)在起,我假定大家知道知道圖4-4.頁面回調(diào)有時,你可能希望向映射到該路徑上的函數(shù)提供的信息。首先,路徑中的其它部分將會自動傳遞過來。讓我們修改一下 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ù)。來自URL的參數(shù)仍然可用;為了它們,你可以修改回調(diào)函數(shù)的簽名,從而添加來自于URLfunctionfun_o($first_name='',$last_name='',$a='',$b='')讓我們做一下測試,將JaneDoe放到頁面參數(shù)中,把JohnDoe放在URL中,然后看看結(jié)果。圖4-6.放在其它文件中的頁面回Drupal會假定你把頁面回調(diào)放在了.module文件中。在Drupal6中,對于每個頁面請求,為了盡可能的降低為其加載的代碼總量,許多模塊被拆分成了多個部分。如果回調(diào)函數(shù)不在當前的.module文件中的話,可以使用菜單項中的file鍵,來指定哪個文件包含了該函數(shù)。我們在第2章中編寫注釋模塊的時候,就用到了file鍵。如果你定義了fileDrupal將會在你的模塊下查找該文件。如果你的頁面回調(diào)是由其它模Drupal在查找該文件時所用的文件路向?qū)Ш絽^(qū)塊中添加一 簡單的映射到一個回調(diào)函數(shù)上了,而是讓Drupal把它作為一個菜單包含進來。提示因為 () 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個菜單項(fun/farewell)的路徑是第一個菜單項路徑(fun)的孩子。因此,在顯示菜單時(轉(zhuǎn)化為HTML),Drupal將會縮進第2個菜單項,如圖4-9所示。它還在頁面的頂部正確的設(shè)置了面包屑,以指示嵌套關(guān)系。當然,根據(jù)設(shè)計者的要求,可將菜單或面包屑顯示成所要的樣式。4-9.嵌套控可以我們的菜單。一般情況下,通過在模塊中使用hook_perm()來定義權(quán)限,并使用一個函數(shù)來測試這些權(quán)限,從而義一個名為receivegreeting的權(quán)限;如果用戶沒有哪個角色具有該權(quán)限的話,當他/她頁面/?q=fun時,將會收到一個“”消息*Implementationof fun_perm(){}*Implementationof () fun']array('title'=>'pagecallback'=> 'accesscallback'=>'accessarguments'=>array('receive'weight'=>- array('title'=>'pagecallback'=> return}面的代碼中,是根據(jù)user_access('receivegreeting')的返回結(jié)果來判定是否允許的。這樣,菜單系統(tǒng)就相提示user_access()函數(shù)是默認的回調(diào)。如果你沒有定義回調(diào)的話,那么參數(shù)將被菜單系統(tǒng)傳遞子菜單一般不會繼承父菜單項的回調(diào)和參數(shù)。所以必須為每個菜單項定義accessarguments鍵。如果回調(diào)不是user_accessaccesscallback標題的本地化和定'title'=>t('Greeting')//No!don'tuset() itemtitlesor然而,你想錯了。菜單字符串是以原始字符串的形式在_router表中的,而菜單項的翻譯則被推了運行時進行。真實情況是,Drupal有一個默認的翻譯函數(shù)(t()函數(shù)),它被指定用來翻譯菜單標題。你將在后面看到,如何將默認翻譯函數(shù)修改為你選擇的函數(shù),以及如何向該函數(shù)傳遞參數(shù)。負責翻譯的函數(shù)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 翻譯兼職合同
- 簡式房屋買賣定金合同范本
- 詳見建設(shè)工程施工合同GF
- 紅酒運輸資質(zhì)轉(zhuǎn)讓合同范本
- 車輛貨物運輸合同
- 宅基地轉(zhuǎn)讓協(xié)議合同書
- 外賣訂單配送承包合同
- 正交薄壁孔音叉陀螺的設(shè)計和性能研究
- 極區(qū)弱觀測環(huán)境下的SINS-DVL-GNSS組合導航算法研究
- 2025年南寧貨運從業(yè)資格證試題答題APP
- 再見深海合唱簡譜【珠海童年樹合唱團】
- 高中物理 選修1 第四章 光(折射反射干涉衍射偏振)(2024人教版)
- 《聚焦客戶創(chuàng)造價值》課件
- PTW-UNIDOS-E-放射劑量儀中文說明書
- 保險學(第五版)課件全套 魏華林 第0-18章 緒論、風險與保險- 保險市場監(jiān)管、附章:社會保險
- 許小年:淺析日本失去的30年-兼評“資產(chǎn)負債表衰退”
- 典范英語2b課文電子書
- 17~18世紀意大利歌劇探析
- β內(nèi)酰胺類抗生素與合理用藥
- 何以中國:公元前2000年的中原圖景
- 第一章:公共政策理論模型
評論
0/150
提交評論