Drupal7學習筆記之Theme

 

Drupal7學習筆記之Theme感覺非常好轉來共享啊!


模板語言和主題引擎

用Drupal的行話來說,主題就是一組負責你站點外觀的文件。你可以從http://drupal.org/project/Themes下載第3方主題,或者你可以自己動手創建一個主題,後者正是你在本章將要學習的。作爲一個web設計者,主題由你所熟悉的大部分內容所組成:樣式表,圖片,JavaScript文件,等等。你將發現,在Drupal主題和純HTML站點之間的區別就是模板文件。這些文件一般都包含大段的靜態HTML,和一些小段的用來插入動態內容的代碼。它們負責你站點的一個特定部分的外觀。模板文件的語法依賴於它所使用的主題引擎。例如,列表8-1,8-2,8-3列出了3個模板文件的代碼片段,它們輸出的內容是一樣但是包含的模板文件內容卻完全不同。

構建一個PHPTemplate主題

創建一個主題,可以有多種方式,這取決於你的起始材料。假定你的設計者已經爲你的站點提供了HTML和CSS文件。那麼將設計者的設計轉化爲一個Drupal主題,到底難不難呢?它實際上不是很難,而且你能夠輕易的完成工作的80%。不過還有20%—最後的難點了—它是 Drupal主題製作高手與新手的分水嶺。首先讓我們從簡單的部分開始。這裏有個概括:

  • 爲站點創建或修改HTML文件
  • 爲站點創建或修改CSS文件
  • 創建一個.info文件,來向Drupal描述你的新主題。
  • 按照Drupal的標準爲文件命名。
  • 在你的模板中,插入可用的變量。
  • 爲單獨的節點類型,區塊,等等創建模板文件。

每個theme至少包含一個描述文件.info,其它如果沒有則使用系統默認文件。主要包括模板文件,CSS文件等。

理解Drupal自帶模板文件

template.php

每個theme都可以包含一個template.php文件,用來包含邏輯代碼,這個文件Drupal會自動載入的,我認爲這個文件相對於Drupal模塊的.module文件一樣。其實一個theme和一個module非常相似,例如.info文件的寫法以及template文件和.module文件的寫法非常相似。

所以我可以在template.php文件裏,我們可以實現hook_theme等,此時你就認爲theme是一個module好了。

theme機制介紹

當Drupal想要爲一個可主題化的項目(比如節點,區塊,麪包屑,評論,或者用戶簽名)生成一些HTML輸出時,它將查找用來爲該項目生成HTML的主題函數或者模板文件。Drupal的所有部分,基本上都是可主題化的,這意味着,對於爲該項目實際生成的HTML,你可以進行覆寫。

Drupal的主題系統背後的核心哲理和鉤子系統的類似。通過遵循命名規範,就可以標識出哪些函數是主題相關的函數,它們負責格式化並返回你站點的內容,或者使用模板文件負責輸出HTML內容。

因此我們要輸出內容時一定要用theme機制實現,方便維護擴展,實現一個theme輸出主要有以下幾個步驟:

  • 實現hook_theme(),目的是註冊我們的theme,會被寫入theme註冊表,當調用theme(‘themename’)時會去theme註冊表查找該theme。
  • 使用函數或模板輸出內容。函數以theme_開頭,例如theme_breakcrumb()。如果是模板文件則以.tpl.php結尾。
  • 實現hook_preprocess_HOOK來爲我們的輸出theme輸出準備變量,這步不是必須的。
  • 其它開發人員如果要覆蓋你的輸出,則在他們的theme中按照一定的規則來覆蓋。

下面將詳細介紹整個過程,我們假定創建了helloTheme的theme,以及helloModule的module,用於展示我們的代碼。

theme_hook介紹

theme_hook通常在module中實現,事實上我們也可以在theme實現theme_hook,例如helloTheme_theme()。因爲我們之前說過一個theme某種程度上來說就是一個module。

        function helloModule_theme() {
          return array(
            //theme_function的寫法
            'hello' => array(
              'variables' => array('abc' => NULL),
            ),

            //模板文件的寫法
            'test' => array(
              'variables' => array('abc' => NULL),
              'template' => 'test',
            ),
         );
        }

theme_hook在Drupal6和Drupal7中寫法是有點區別的,例如Drupal7中使用variables來傳遞變量,每個theme函數都會有個$variable參數。而Drupal6是用arguments。另外Drupal7中還引入了render element的寫法,具體見hook_theme

Drupal自帶的每個module基本上都實現了hook_theme,Drupal的核心theme的定義是在System模塊裏的system_theme中實現的,裏面調用了drupal_common_theme()函數來定義Drupal的核心theme,比如breadcrumb, table等。

theme函數輸出

函數以theme_開頭,加上我們註冊的theme名稱,例如我們上面註冊了hello的theme,則該theme函數的函數名爲theme_hello()。我們通過theme(‘hello’, array(‘abc’ => ‘Hello’))來調用我們的theme函數,abc這個參數可以通過$variable來獲取。Drupal會爲每個theme函數傳遞一個數組進來的,裏面包含了所有的變量。

        function theme_hello($variables) {
          return "You say " . $variable['abc'];
        }

是選擇theme函數還是theme模板輸出,取決於你側重點。theme函數性能較好,執行較快,但是對於前端開發人員不友好,需要去理解PHP相關知識,而theme模板輸出對前端開發人員較友好,但是性能很差。

Drupal核心的theme函數都在includes/theme.inc中定義,比如theme_breadcrumb(), theme_table等。

theme模板輸出

根據theme_hook裏定義的模板文件名,我們需要在我們的module目錄下面創建一個test.tpl.php,在模板文件裏,我們可以直接通過$variables來獲取我們傳進去的參數,如$variables['abc'],同時Drupal會把參數直接轉換成變量,因此我們也可以直接訪問$abc。

        <h2>You say <?php print $abc; ?></h2>

Drupal中核心的模板文件都在各自的module目錄下面,比如html.tpl.php, page.tpl.php都在system模塊下面,而node.tpl.php在node目錄下面。

爲輸出準備變量hook_preprocess_HOOK

通常我們在輸出時用到的數據都是調用時直接作爲參數傳進去,例如theme(‘hello’, array(‘abc’ => ‘Hello’)),但是以下情形時我們可以調用預處理函數來準備變量:

  • 我們需要非常多的小的變量,如果通過參數傳遞會太長,因此可以在預處理函數裏進行預處理,將一個大的參數拆分成許多小的變量,典型的例子是node模塊爲node.tpl.php準備變量,參考node.module中的template_preprocess_node()函數。
  • 我們擴展別人的theme輸出,或者不確定我們的參數時,我們可以在預處理函數來處理這些變量。

hook_preprocess_HOOK中的hook是指module名稱或theme名稱,HOOK是指我們定義的theme的名稱,比如helloModule_preprocess_hello(),預處理函數會被自動調用,我們只需要按照命名規則書寫就可以了。

我們以page.tpl.php爲例來看看預處理函數是怎麼工作的。在includes/theme.inc中有個template_preprocess_page用來給page.tpl.php準備各種變量,如果對page.tpl.php熟悉的話,應該知道page.tpl.php中有好多變量是可以直接使用的,比如$logo, $tabs, $language等,都是在這裏預定義的,在theme函數裏,可以通過$variables['logo']來訪問,而在模板文件中,Drupal會把這些變量轉換成直接變量,比如logo,我們既可以通過$variables['logo']來訪問,也可以通過$logo來訪問。

theme輸出的覆蓋

使用theme機制輸出的最大好處就是我們可以用自己的theme輸出來覆蓋別人的theme輸出,從而達到擴展的目的。以上面定義的hello爲例,會按照以下的優先級來執行:

        helloTheme_hello()
        sites/all/themes/helloTheme/hello.tpl.php
        theme_hello()

phptemplate_hello()這種寫法在Drupal7中已經被取消了,就是在Drupal7的theme中,所有的前綴必須是themeName + “_”,例如galand_, helloTheme_等。

覆寫theme的常見做法就是在自己的theme目錄下建tpl模板文件或在temmplate.php中創建theme函數。對於tpl模板文件,同樣的文件在theme目錄下優先級是更高的,比如我們覆蓋node.tpl.php。

hook_preprocess_HOOK的覆寫

我們前面說過hook_preprocess_HOOK是用來給theme函數或模板準備變量的,但是它也是有好多寫法,有不同的執行順序的,

        template_preprocess()
        template_preprocess_hello()
        helloModule_preprocess()
        helloModule_preprocess_hello()
        phptemplate_preprocess()
        phptemplate_preprocess_hello()
        helloTheme_preprocess()
        helloTheme_preprocess_hello()
        template_process()

上面提到的所有函數是從一個到最後一個順序執行的,就是說,如果上面的函數都存在,就會都執行一遍,如果他們提供了同名的變量,則後面的覆蓋前面的。這個和theme輸出是不一樣的,theme輸出只會執行優先級最高的那個。

這裏還是以template_preprocess_page爲例,這裏會先執行template_preprocess_page(),然後在執行template_process(),如果我們在theme裏定義了helloTheme_preprocess_page(),則會在template_process()之前執行。

Drupal中模板文件命名規則

上面說過,theme下面的同名模板文件比module下面的優先級高,比如helloTheme/node.tpl.php就比node/node.tpl.php優先級高,但是模板文件還可以根據命名的規則來確定優先級:

1、block–[region[module--delta]].tpl.php

基於主題文件: block.tpl.php

block–module–delta.tpl.php

block–module.tpl.php

block–region.tpl.php

2、comment–[node-type].tpl.php

基於主題文件: comment.tpl.php

3、comment-wrapper–[node-type].tpl.php

基於主題文件: comment-wrapper.tpl.php

4、forums–[[containertopic]–forumID].tpl.php

基於主題文件: forums.tpl.php

For forum containers:

forums–containers–forumID.tpl.php

forums–forumID.tpl.php

forums–containers.tpl.php

For forum topics:

forums–topics–forumID.tpl.php

forums–forumID.tpl.php

forums–topics.tpl.php

5、maintenance-page–[offline].tpl.php

基於主題文件: maintenance-page.tpl.php

6、node–[typenodeid].tpl.php

基於主題文件: node.tpl.php

node–nodeid.tpl.php

node–type.tpl.php

node.tpl.php

7、page–[frontinternal/path].tpl.php

基於主題文件: page.tpl.php

page–node–edit.tpl.php

page–node–1.tpl.php

page–node.tpl.php

page.tpl.php

page.tpl.php (this is always a suggestion)

page–node.tpl.php (and prefix is set to page__node)

page–node–%.tpl.php

page–node–1.tpl.php (prefix is not changed because the component is a number)

page–node–edit.tpl.php (and prefix is set to page__node__edit)

page–front.tpl.php (but only if node/1/edit is the front page)

8、poll-results–[block].tpl.php

基於主題文件: poll-results.tpl.php

9、poll-vote–[block].tpl.php

基於主題文件: poll-vote.tpl.php

10、poll-bar–[block].tpl.php

基於主題文件: poll-bar.tpl.php

11、profile-wrapper–[field].tpl.php

基於主題文件: profile-wrapper.tpl.php

12、search-results–[searchType].tpl.php

基於主題文件: search-results.tpl.php

13、search-result–[searchType].tpl.php

基於主題文件: search-result.tpl.php

Theme的調試輸出

  • render(), hide()函數,這兩個函數是Drupal7新加的,便於可使節點的打印輸出更精細,render()用來構造內容,比如print render($page['highlighted']);,因爲Drupal對構造過的內容會做標識,下次不會再次構造,因此hide()就是把標識去掉,可以接着render了。
  • Devel是個強大的Drupal開發工具,主題開發者模塊是依賴於Devel的一個模塊,能夠讓你指定一個頁面元素,來查看生成該元素所用到的模板文件和主題函數,以及對於該元素都有哪些變量(和它們的值)可用。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章