利用中のカスタムモジュールのテーブル定義を変更する

  •  
 
ナカちゃん2019年7月29日 - 10:44 に投稿

タグ

2019/8/5 追記:hook_post_update_NAME()ではなく、hook_update_N()を使用するように変更しました。

はじめに

使用しているカスタムモジュールに機能追加した場合、使用しているDBテーブルの定義を変更する必要が出てきたりします。
Drupalでは「モジュールのアップデート」でDB定義を変更することができるようなので、その方法を試してみます。

1. 前提(環境情報)

  • Drupal: 8.7
  • PHP: 7.2
  • そのほかDB,webサーバなどはよしなに...

 

また、カスタムモジュールとして"sample"という名前のモジュールがインストールされており、
sample.installにて以下のDBテーブルが定義されているものとします。

<?php
 ・
 ・
 ・
function sample_schema(){
  $schema['sample_greeting'] = [
    'description' => 'greeting messages',
    'fields' => [
      'id' => [
        'description' => 'identifier',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ],
      'message_text' => [
        'description' => 'greeting message',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
      ],
    ],
    'primary key' => [
      'id',
    ],
  ];
  return $schema;
}
 ・
 ・
 ・

 

上記テーブルには、レコードが存在するものとします。

mysql> select * from sample_greeting;
+----+--------------+
| id | message_text |
+----+--------------+
|  1 | Bonjour      |
|  2 | Hujambo      |
|  3 | konnichiwa   |
|  4 | Hi there     |
+----+--------------+

 

 

それでは、上記のテーブルににnationalityカラムを追加してみます。

2. モジュールの修正

追加カラムの定義をsample.installに追記する。

<?php
 ・
 ・
 ・
function sample_schema(){
  $schema['sample_greeting'] = [
    'description' =--> 'greeting messages',
    'fields' => [
      'id' => [
        'description' => 'identifier',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ],
      'message_text' => [
        'description' => 'greeting message',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
      ],
      //追加カラム
      'nationality' => [
        'description' => 'nationality',
        'type' => 'varchar',
        'length' => 255,
        'not null' => FALSE,
      ],
    ],
    'primary key' => [
      'id',
    ],
  ];

  return $schema;
}
 ・
 ・
 ・

 

続けて同ファイルにhook_post_update_Nを実装し、
テーブル定義を変更するコードを記述する。

/**
 * Add a nationality column to the sample_greeting table.
 */
function sample_update_8101() {
  //Nの部分は、以下の数字を組み合わせた4または5桁の数字に置き換える
  //上位桁から順番に
   //  1桁、または2桁のDrupalのcoreバージョン(8,9,10など)を表す数字
   //  1桁のカスタムモジュールのバージョンを表す数字(8.x-1.*なら1,8.x-2.*なら2といった具合)
   //  2桁の通し番号。(01からカウントアップ)
   //となる。
  $specification = [
    'description' => 'nationality',
    'type' => 'varchar',
    'length' => 255,
    'not null' => FALSE
  ];

  $schema = Database::getConnection()->schema();
  $schema->addField('sample_greeting', 'nationality', $specification);
}

 

sample.info.ymlに記載しているモジュールバージョンの変更 

name: sample
type: module
description: sample
core: 8.x
package: sample

#1.0 -> 1.1に
version: '8.x-1.1'
core: '8.x'

3. update.phpの実行

update.phpにブラウザでアクセスし、[継続]。

img

 

更新内容が表示されるので、[保留中のアップデートを適用する]。

img

 

適用完了。

img

4. 確認

既存レコードを壊さずに、カラムの追加ができた。

mysql> select * from sample_greeting;
+----+--------------+-------------+
| id | message_text | nationality |
+----+--------------+-------------+
|  1 | Bonjour      | NULL        |
|  2 | Hujambo      | NULL        |
|  3 | konnichiwa   | NULL        |
|  4 | Hi there     | NULL        |
+----+--------------+-------------+
4 rows in set (0.00 sec)

その他注意点など

・似たようなことができるhookとしてhook_post_update_NAME()というのがある。

hook_post_update_NAME()が呼び出されるのは実装されたhook_update_N()が全て実行された後。
また、このhookはEntityの更新に使うことが主な目的のため、今回のようにモジュールのアップデート目的で使うべきではないようです。

参考

コメントを追加

プレーンテキスト

  • HTMLタグは利用できません。
  • 行と段落は自動的に折り返されます。
  • ウェブページのアドレスとメールアドレスは自動的にリンクに変換されます。
CAPTCHA
この質問はあなたが人間の訪問者であるかどうかをテストし、自動化されたスパム送信を防ぐためのものです。