您在這裡

把玩Drupal模組: Hook System運作簡介

jimmy's 的頭像
jimmy 在 2006-05-09 (二) 20:07 發表

模組系統是drupal很重要的運作方式,drupal依靠著少少的核心程式,便能讓模組能做到任何事情。

drupal只有21個檔案在include裡頭,每次必會loading進來,其他的全都放在modules。
也就是說,除了那幾隻檔案以外,全部的東西都把他當成module在寫。諸如CMS最基本的功能,文章管理、評論、討論區、分類...等的功能,全部都寫在module裡,include裡頭所提供的是各種api,檔案處理函式、資料庫存取、表單生成...等等,這樣的分層,module便可以專心的開發各種功能。

當然,這樣的架構不夠令人注目。有許多web app架構,對於模組 (module)、插件(plug-in)...等的運作,通常是讓他們各自為政,自己幹自己的事情。多是用核心提供的object和function,加上module自己額外的code,達到module要做到的額外功能。但是drupal的核心運作卻不是如此。

drupal處理使用的程式為modules/user.module。如果今天想要在看使用者資料的同時,也想看看所有使用者過去發表文章的list,那該怎麼寫呢?

直接一點,更改user.modue,在顯示時,順便去文章資料庫抓相關的資料?然而這樣卻不是一個好方式,今天任何想要對使用者增加新功能的時候,都得trace一次user.module的code,看懂他在幹啥,然後把新的code安插在合適的地方... 最後可能增加user.module的複雜度,增加維護那支module的難度,共同開發時,更是一個危險的方式。

第二種方式,重寫一個新的瀏覽頁面,重新寫一個SELECT的語句,讓SELECT的時候除了使用者資訊,也把文章資料一起抓出來,然後顯示到不同的頁面。但是這樣很浪費,明明跟user.module重複的功能達到一半以上,那是不是之後要新增功能,都得重寫一次呢?

上面兩種方式在drupal中也都可以達成,然而熟悉Drupal的人卻不會如此。Drupal的開發者很聰明,他的模組系統(module system)考慮到了模組再利用這一點,每個模組都視為可以再利用的資源,只要寫module的人想寫,透過模組系統便可以跟所有的module交互作用。

第三種方式modules/user.module為例,他即是處理包含新增、修改、刪除、註冊、登入....等所有與使用者相關的功能。在進行每個重要的功能時,user.module都會呼叫一個函式去掃所有的module,看看是否有其他的module要在user.module進行此動作時,也進行一些其他想要做的事情,這就是drupal重要的Hook System
example:
在drupal user.module裡頭可以找到如下的程式碼

function user_view($uid = 0) {
  // ... skip
  // moudle_invoke掃描所有的module
  // 看看有沒有modulename_user這個function
  // 有個話就看'view'這個功能的部份要加上什麼
  foreach (module_list() as $module) {
    if ($data = module_invoke($module, 'user', 'view', '', $account)) {
      // do something...
    }
  }
  // ... skip
}

所以,第三種方式,不用重寫,也不用改到user.module,只要自己新增module和寫一個function,便可以輕鬆讓瀏覽使用者資訊時,加上過往文章。
example:
新增自己的module,與hook system緊密運作
新增sample.module

function sample_user($type, &$edit, &$user, $category = NULL) {
  if ($type == 'view') {
    return /*過往文章,型別為一陣列*/;
  }
}

這就是drupal把眾多主要功能都寫成module的原因,讓所有模組之間都可以交互利用,或是寫給別人利用,或是利用別人的module,像積木一樣推砌成想要的功能,卻又不浪費資源。

參考資源:
詳細的用法在:
http://drupaldocs.org/api/head/function/hook_user
Module developer's guide:
http://drupal.org/node/508