跳到正文
gloomcheng/

ARCHIVE / 

[Drupal] 自訂資料表及與 Views 整合

本文適用於 Drupal 7。

自訂資料表

如果你需要建構 custom table,那麼你可以用 hook_schema() 來定義資料表結構。 在開始前,建議可以閱讀 Schema API quick start guide

/**
 * Implements hook_schema().
 */
function mymodule_schema() {
  $schema['custom_table1'] = array(
     // 定義資料欄位
  );
  $schema['custom_table2'] = array(
     // 定義資料欄位
  );
  return $schema;
}

上述中,table 陣列下就是定義你這個資料表需要的資料欄位。以 node 模組為例,node table 下每個欄位基本上可以設定以下參數

$schema['node'] = array(
  'description' => 'The base table for nodes.',
  'fields' => array(
    'nid' => array(
      'type' => 'serial',
      'unsigned' => TRUE,
      'not null' => TRUE,
    ),
);

基本上,一定會定義每個資料欄位的資料型態(type)。Drupal 的 Schema API 提供有 自動編序Serial、整數Integer、浮點數Float、小數Decimal (Numeric)、文字Text、變動長度長文字Varchar、固定長度長文字Char及二進位大型物件Blob等資料類型。你可以根據自己的需求來規劃各欄位要儲存什麼類型的資料,例如如果你需要流水序號,可以用 Serial;如果需要儲存 nid 或 uid 來當 foreign key,那可以用 Integer。比例特別的是,如果你需要儲存建立時間、變更時間等資料,通常也會用 Integer 來儲存 UNIXSTAMP 的時間值。

不同的資料型態,則會額外的參數可以設定。例如 intfloatdecimal 這三種類型,可以加上 unsigned 參數來設定此欄位是否可以存「負值」,例如 unsigned => TRUE 就是不允許儲存負值(不允許使用正負號)。另外還有諸如 not nulldefault 等也是常用的設定參數,在 Schema Reference 一文有詳細的說明,建議可以仔細讀一讀。

最後,設定完資料欄位外,如果你熟悉資料庫的運作,應該會想到 primary keyforeign key 等設定,沒錯,這同樣是在 schema 裡一併設置的。同樣拿 node 模組的 node table 來說明:

$schema['node'] = array(
  'description' => 'The base table for nodes.',
  'fields' => array(
    'nid' => array(
      'type' => 'serial',
      'unsigned' => TRUE,
      'not null' => TRUE,
    ),
   ...
  // For documentation purposes only; foreign keys are not created in the
  // database.
  'foreign keys' => array(
    'node_revision' => array(
      'table' => 'node_revision',
      'columns' => array(
        'vid' => 'vid',
      ),
    ),
    'node_author' => array(
      'table' => 'users',
      'columns' => array(
        'uid' => 'uid',
      ),
    ),
  ),
  'primary key' => array(
    'nid',
  ),
);

當然,一旦開始要設計資料表結構時,一定還是手足無措,一堆問題找不到,所以建議可以參考 Schema API,裡面是提供 node 的 schema 設計,很詳細,該用到的參數都用到了,可以當參考範例。

如果沒有在啟用模組前就定義好 schema

此時,你除了用 hook_schema() 外,還需要用 hook_update_N(),透過 Drupal 的更新機制,來更新資料結構(包含資料表的建立、刪除,以及資料欄位的建立、調整、刪除等)。

function mymodule_update_6100() {
  $schema = drupal_get_schema('custom_table1');
  db_add_field('custom_table1', 'newcol', $schema['newcol']);
}

與 Views 整合

要讓 Views 可以讀得到前面自定的資料表,簡單一點你可以用 Views Custom Table 模組,參考頁面的圖示說明操作,你就可以快速的達到跟 Views 整合的效果。

如果你想嘗試 hardcore,那麼 Exposing Tables to Views in Drupal 7 這篇文章給我們一個指引。

要讓客製模組跟 Views 整合,首先要在模組的 .module 檔案,定義 Views API 版本。

/**
 * Implements hook_views_api().
 */
function mymodule_views_api()
{
    return array(
        'api' => 3,
        'path' => drupal_get_path('module', 'expose') . '/includes/views',
    );
}

然後,再建立 mymodule.views.inc 檔案並放到 mymodule/includes/views 資料夾下(如果你想放到 mymodule/includees 下,記得上面那段程式中的 path 也要跟著改)。

接著我們需要透過 hook_views_data() 來加入 Views 的支援,詳細範例可以直接參考 How to join user table with another table in views data 一文,還滿清楚的。比較特別的是,如果我們今天設計的資料表有 uid 欄位,而且透過此欄位來參照到 users 資料表,進而取得使用者的名稱、Email 等資訊的話,那麼關鍵在下面範例的 relationship 那邊,透過此處的設置,等於是讓我們在 Views 「關聯」區域可以有一個可以加入使用的欄位,名稱叫做「Author」(如果常用 Drupal Views 的,應該不陌生,例如我們先用「Content」資料表時,想進一步抓到文章的作者個資,就會在關聯加入「Author」欄位)。

function node_views_data() {
  ..
  // uid field
  $data['node']['uid'] = array(
    'title' => t('Author uid'),
    'help' => t('The user authoring the content. If you need more fields than the uid add the content: author relationship'),
    'relationship' => array(
      'title' => t('Author'),
      'help' => t('Relate content to the user who created it.'),
      'handler' => 'views_handler_relationship',
      'base' => 'users',
      'field' => 'uid',
      'label' => t('author'),
    ),
    'filter' => array(
      'handler' => 'views_handler_filter_user_name',
    ),
    'argument' => array(
      'handler' => 'views_handler_argument_numeric',
    ),
    'field' => array(
      'handler' => 'views_handler_field_user',
    ),
  );
  ..
}

其實 views_data() 設計的很完整,但一開始接觸應該還是多少搞不太懂邏輯,除了上述 node 模組的範例外,建議還可以看看 user_views_data() 的程式範例,兩相比較應該比較好懂。尤其 Content 和 User 本來就是使用 Views 最常用到的資料表,結合平時的操作經驗,發揮聯想,會比較容易對程式碼有感覺。

有沒有更簡單的方法?

使用 Drupal 近十年的時間,幾乎什麼需求、疑難雜症在 Drupal 社群上都會找到解方,僅管不一定完全合適,但總是一個方向。例如我在找資料過程中,找到 Data 模組,看來是一個可以透過後台 UI 建立資料表、調整資料結構的利器。有興趣的就自行試試囉!