※画像はテーブル作成(物理)の様子です。

この記事ではカスタムモジュールでテーブルをデータベースに追加する際に使うhook_schema という関数のパラメーターについて説明します。hook_schemaのチュートリアルについてはこちらを御覧ください。

hook_schemaの構造

hook_schemaはモジュール内の.installファイルの中で定義されます。hook_schema内では、$schemaという変数の中にテーブルを定義し、最後に$schemaを返すことでテーブルがデータベースに登録されます。

テーブルの宣言

$schema['TABLE_NAME'] =[テーブルの定義];

と書くことでテーブルを宣言します。上記のコードをテーブルごとに書くことで複数のテーブルを$schemaに含めることが出来ます。

$schema['table1']=[...];
$schema['table2']=[...];

その場合は、モジュールをインストールすると$schemaの中で宣言したすべてのテーブルがデータベースに登録されます。

テーブル内のパラメーター

$schema['[テーブル名]']の直下にくるパラメーターには以下のようなものがあります。

  • 'field': カラムの定義(必須)
  • 'description' : テーブルの説明(オプション)
  • 'primary keys' : プライマリーキー(オプション)
  • 'unique keys' : ユニークキー(オプション)
  • 'foreign keys': 外部キー(オプション)
  • 'indexes': インデックス(オプション)

以下、それぞれの詳細について解説していきます。

field

fieldではフィールド(カラム)に入るデータの形式を定義します。 さまざまなパラメーターがありますが、typeのみが必須で、残りはオプションです。 ただし、typenumericのときはprecisionscaleが、typevarcharのときはlengthが必須になります。

  • description: フィールドの説明。 他のテーブルについて言及する場合は、{[テーブル名]}のように{}で囲う必要があります。(筆者注:おそらく見やすさのため。)
  • type: データ型。Drupalで定められた型名を使うことで、データベースのエンジン固有の型に自動的にマッピングされます。 使える型名は以下の通り。
    • varchar
    • char
    • int
    • serial
    • float
    • numeric
    • text
    • blob
    • datetime
    • serial
  • mysql_type, pgsql_type, sqlite_type等: データベースドライバーに固有のタイプ。例えば、'mysql_type' => 'TIME''pgsql_type' => 'time without time zone'と同じです。
  • size: データのサイズ。上限量を決めるとともにデータベース固有のデータ型のヒントになります。例えば、データ型がintでデータサイズがtinyだと、MySQLではTINYINTとして読み込まれます。使えるサイズ名は以下です。
    • tiny
    • small
    • medium
    • normal
    • big
      データ型とサイズについては こちらに詳しい情報があります。
  • not null: trueの場合、空白が許可されます。 デフォルトではfalseになっています。
  • default: フィールドのデフォルト値。PHPのデータ型に従って値が識別されるため、 '''0'0はすべて別モノとして扱われるので注意。タイプがtextblobのフィールドはデフォルト値を持つことが出来ません。
  • length: データ型がcharvarchartextのフィールドに対して、長さを指定します。他のデータ型に対して指定しても無視されます。varcharに対しては必須です。
  • unsigned: データ型がintfloatnumericのデータで下限を0にするか(マイナスを扱わないか)どうかを決めるboolean値。デフォルトではFALSE。他のデータ型のフィールドでは無視される。
  • precision, scale: データ型がnumericのフィールドに対し、 precision(桁数) とscale(小数点の右側の桁数)を指定します。両方とも必須です。他のデータ型に対しては設定しても無視されます。
  • serialize: フィールドがシリアライズされるかどうかを示すboolean値です。
  • binary: データ型がcharvarchartextのフィールドに対して MySQLが大文字と小文字を区別するバイナリーの照合順序を使うかどうかを指定するboolean値です。他のデータ型では大文字と小文字を区別するのがデフォルトなので無視されます。
'fields' => [
      'nid' => [
        'description' => 'The {node}.nid this record affects.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ],
],

description

テーブルとその目的について説明するプレーンテキストの文章です。他のテーブルに言及する場合は{}でテーブル名を囲わなくてはいけません。

'description' => 'Stores per-revision title and body data for each {node}.',

primary key

プライマリーキーを構成する配列。一つ以上のフィールドを指定します。

'primary keys' => ['uid', 'module', 'name'],

unique keys

ユニークキーを定義する連想配列。 '[キー名]' => [フィールドの指定]という形式で書きます。 「フィールドの指定」部分には一つか複数のフィールドから成る配列が入ります。

'unique keys' => [
        'vid' => ['vid']
        ], 

foreign keys

外部キーを定義する連想配列。 '[リレーション名]' => [リレーションの指定]という形式で書きます。 「リレーションの指定」部分には参照先のテーブル('table')とフィールドのマッピング情報('column')が入ります。 フィールドのマッピング情報は'[ソースとなるフィールド]' => '[参照先のフィールド]'という形式で書きます。 外部キーはデータベースでは作られず、Drupalで強制されているわけでもありません。

'foreign keys' => [
      'affected_node' => [
        'table' => 'node',
        'columns' => ['nid' => 'nid'],
      ],
    ],

indexes

インデックスを定義する連想配列。 '[インデックス名]' => [インデックスの指定]という形式で書きます。 「インデックスの指定」部分には一つ以上のキーとなるフィールドを指定します。

'indexes' => [
      'module' => ['module'],
      'name' => ['name'],
    ],

ノードモジュールのhook_schema

最後に、ノードモジュールのhook_schemaを転載しておきますのでご参考にしていただければと思います。

**
 * Implements hook_schema().
 */
function node_schema() {
  $schema['node_access'] = [
    'description' => 'Identifies which realm/grant pairs a user must possess in order to view, update, or delete specific nodes.',
    'fields' => [
      'nid' => [
        'description' => 'The {node}.nid this record affects.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ],
      'langcode' => [
        'description' => 'The {language}.langcode of this node.',
        'type' => 'varchar_ascii',
        'length' => 12,
        'not null' => TRUE,
        'default' => '',
      ],
      'fallback' => [
        'description' => 'Boolean indicating whether this record should be used as a fallback if a language condition is not provided.',
        'type' =>'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 1,
        'size' => 'tiny',
      ],
      'gid' => [
        'description' => "The grant ID a user must possess in the specified realm to gain this row's privileges on the node.",
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ],
      'realm' => [
        'description' => 'The realm in which the user must possess the grant ID. Modules can define one or more realms by implementing hook_node_grants().',
        'type' => 'varchar_ascii',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ],
      'grant_view' => [
        'description' => 'Boolean indicating whether a user with the realm/grant pair can view this node.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
        'size' => 'tiny',
      ],
      'grant_update' => [
        'description' => 'Boolean indicating whether a user with the realm/grant pair can edit this node.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
        'size' => 'tiny',
      ],
      'grant_delete' => [
        'description' => 'Boolean indicating whether a user with the realm/grant pair can delete this node.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
        'size' => 'tiny',
      ],
    ],
    'primary key' => ['nid', 'gid', 'realm', 'langcode'],
    'foreign keys' => [
      'affected_node' => [
        'table' => 'node',
        'columns' => ['nid' => 'nid'],
      ],
    ],
  ];

  return $schema;
}