[Drupal7]既に設定済みのFIELDTYPEをintegerからtextへ変更。

by codechord. 0 Comments

  • このエントリーをはてなブックマークに追加
  • このエントリーをはてなブックマークに追加

Drupalでサイトの改修していて、既に設定した任意のContent Typesの一部のフィールドの型を変換する必要がありました。(「Integer」型→「text」型へ)
Drupalの管理画面から行えず、Moduleもありませんでしたので、直接データベースの値を修正することになりました。作業時間1時間弱といったところです。検索してもみつからなかったので、せっかくですので、その手順を残しておきます。

手順

この手順は、Integer→textへの型変換の方法です。他の型の場合は手順2,3,4あたりの値が異なってくると思います。

  1. Databaseバックアップ
  2. Table「field_data_field_xxx」の構造を変更
    同様に、Table「field_revision_field_xxx」の構造を変更
  3. Table「field_config」のレコードを変更
  4. Table「field_config_instance」のレコードを変更
  5. フォーマットを指定していた場合、Manage Displayページからフォーマットをリセット。
  6. Drupalキャッシュクリア

1. Databaseをバックアップ

失敗しても復旧できるように。テーブルのバックアップか、データベースのバックアップします。

2. Table「field_data_field_xxx」と「field_revision_field_xxx」の構造を変更

Drupalでは新たなフィールドタイプを作成すると、自動的に、「field_data_field_<fieldtype名>」と「field_revision_field_<fieldtype名>」といった名前のテーブルが作成されます。
ここではsampleというFieldTypeをInteger型として追加している場合の例です。
構造とレコードをみてみます。

mysql> DESC field_data_field_sample;
+--------------------+------------------+------+-----+---------+-------+
| Field              | Type             | Null | Key | Default | Extra |
+--------------------+------------------+------+-----+---------+-------+
| entity_type        | varchar(128)     | NO   | PRI |         |       |
| bundle             | varchar(128)     | NO   | MUL |         |       |
| deleted            | tinyint(4)       | NO   | PRI | 0       |       |
| entity_id          | int(10) unsigned | NO   | PRI | NULL    |       |
| revision_id        | int(10) unsigned | YES  | MUL | NULL    |       |
| language           | varchar(32)      | NO   | PRI |         |       |
| delta              | int(10) unsigned | NO   | PRI | NULL    |       |
| field_sample_value | int(11)          | YES  |     | NULL    |       |
+--------------------+------------------+------+-----+---------+-------+
8 rows in set (0.00 sec)

mysql> SELECT *  FROM  `field_data_field_sample`  LIMIT 0 , 10;
+-------------+--------+---------+-----------+-------------+----------+-------+--------------------+
| entity_type | bundle | deleted | entity_id | revision_id | language | delta | field_sample_value |
+-------------+--------+---------+-----------+-------------+----------+-------+--------------------+
| node        | pages  |       0 |       225 |         225 | und      |     0 |                  1 |
| node        | pages  |       0 |       226 |         226 | und      |     0 |                  2 |
| node        | pages  |       0 |       227 |         227 | und      |     0 |                  3 |
+-------------+--------+---------+-----------+-------------+----------+-------+--------------------+
3 rows in set (0.00 sec)

このような感じです。一方Text型として追加した場合のfield_dataを見てみます。

mysql> DESC field_data_field_new;
+------------------+------------------+------+-----+---------+-------+
| Field            | Type             | Null | Key | Default | Extra |
+------------------+------------------+------+-----+---------+-------+
| entity_type      | varchar(128)     | NO   | PRI |         |       |
| bundle           | varchar(128)     | NO   | MUL |         |       |
| deleted          | tinyint(4)       | NO   | PRI | 0       |       |
| entity_id        | int(10) unsigned | NO   | PRI | NULL    |       |
| revision_id      | int(10) unsigned | YES  | MUL | NULL    |       |
| language         | varchar(32)      | NO   | PRI |         |       |
| delta            | int(10) unsigned | NO   | PRI | NULL    |       |
| field_new_value  | varchar(255)     | YES  |     | NULL    |       |
| field_new_format | varchar(255)     | YES  | MUL | NULL    |       |
+------------------+------------------+------+-----+---------+-------+

mysql> SELECT *  FROM  `field_data_field_new`  LIMIT 0 , 10;
+-------------+--------+---------+-----------+-------------+----------+-------+-----------------+------------------+
| entity_type | bundle | deleted | entity_id | revision_id | language | delta | field_new_value | field_new_format |
+-------------+--------+---------+-----------+-------------+----------+-------+-----------------+------------------+
| node        | pages  |       0 |       174 |         174 | und      |     0 | abcde           | plain_text       |
+-------------+--------+---------+-----------+-------------+----------+-------+-----------------+------------------+

このような感じです。最後の”plain_text”のところはNULLの場合もあります。
というわけなので、この構造に変更していきます。一つカラム追加する必要がありますね。

変更前
| field_sample_value | int(11)          | YES  |     | NULL    |       |

変更後
| field_sample_value  | varchar(255)     | YES  |     | NULL    |       |
| field_sample_format | varchar(255)     | YES  | MUL | NULL    |       |

リビジョンテーブルの構造も同様に修正します。

3. Table「field_config」のレコードを変更

Table「field_config」のカラム「type, module, data」を修正します。
カラム「data」のレコードはDrupalでの設定情報のserializeされたテキストデータです。

(※ phpmyadminを使って編集する場合は、dataカラムの型を、LongblobからTextに変更すると編集できるようになります。編集後にLongblob型にもどすことを忘れないようにします。)

+----+--------------+----------------+--------+--------+-------------------+-------------------+----------------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------+--------------+---------+
| id | field_name   | type           | module | active | storage_type      | storage_module    | storage_active | locked | data                                                                                                                                                                                                                                                                                                                                                                                                                    | cardinality | translatable | deleted |
+----+--------------+----------------+--------+--------+-------------------+-------------------+----------------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------+--------------+---------+
| 21 | field_sample | number_integer | number |      1 | field_sql_storage | field_sql_storage |              1 |      0 | a:8:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:1:{s:16:"profile2_private";b:0;}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:23:"field_data_field_sample";a:1:{s:5:"value";s:18:"field_sample_value";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:27:"field_revision_field_sample";a:1:{s:5:"value";s:18:"field_sample_value";}}}}}s:12:"foreign keys";a:0:{}s:7:"indexes";a:0:{}s:2:"id";s:2:"21";s:17:"field_permissions";a:1:{s:4:"type";s:1:"0";}} |           1 |            0 |       0 |
+----+--------------+----------------+--------+--------+-------------------+-------------------+----------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------+--------------+---------+

この中のdataカラムの値をコピーし、unserializeし、Text型の設定データへと修正し、serializeし、sqlやphpmyadminなどで再登録します。
Text型の設定データに関しては、既に登録しているであろうText型のFieldTypeのレコードを見本として、serializeのデータの必要項目だけ修正していく流れです。(データの修正は少し神経質な作業・・・)

unserializeとserializeは手っ取り早くwebツールを利用します。

カラム 編集前 編集後
type number_integer text
module number text
data シリアライズされた、 ContentType:integer型の設定情報 シリアライズされた、 ContentType:text型の設定情報
+----+------------+------+--------+--------+-------------------+-------------------+----------------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------+--------------+---------+
| id | field_name | type | module | active | storage_type      | storage_module    | storage_active | locked | data                                                                                                                                                                                                                                                                                                                                                                                                                    | cardinality | translatable | deleted |
+----+------------+------+--------+--------+-------------------+-------------------+----------------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------+--------------+---------+
| 14 | field_new  | text | text   |      1 | field_sql_storage | field_sql_storage |              1 |      0 | a:8:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:2:{s:10:"max_length";s:3:"255";s:16:"profile2_private";b:0;}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:20:"field_data_field_new";a:2:{s:5:"value";s:15:"field_new_value";s:6:"format";s:16:"field_new_format";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:24:"field_revision_field_new";a:2:{s:5:"value";s:15:"field_new_value";s:6:"format";s:16:"field_new_format";}}}}}s:12:"foreign keys";a:1:{s:6:"format";a:2:{s:5:"table";s:13:"filter_format";s:7:"columns";a:1:{s:6:"format";s:6:"format";}}}s:7:"indexes";a:1:{s:6:"format";a:1:{i:0;s:6:"format";}}s:2:"id";s:2:"15";s:17:"field_permissions";a:1:{s:4:"type";s:1:"0";}}  |           1 |            0 |       0 |
+----+------------+------+--------+--------+-------------------+-------------------+----------------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------+--------------+---------+

4. Table「field_config_instance」のレコードを変更

手順3の似たような作業です。
dataカラムのみの変更です。「unserialize→適切に修正→serialize→更新」の流れです。

5. フォーマットを指定していた場合、Manage Displayページからフォーマットをリセット。

任意のContentTypeのManage Displayの管理ページ(http://<ドメイン>/admin/structure/types/manage/<コンテントタイプ>/display)で、対象のFieldTypeのフォーマット設定(数値を3桁ごとに区切るとか、小数点以下◯桁を表示等)が残ったままの場合は、その設定を削除します。

6. Drupalキャッシュクリア

最後にDrupalのキャッシュをクリア。これでIntegerからTextになりました。
Integerのまま変更されていなかったらきっと手順3or4の設定間違いが考えられます。もしくは、手順5のフォーマットに古い型での設定情報が残ってる場合も考えられます。

まとめ

面倒です。もっと簡単な方法があれば教えて下さい。
なお、この逆の手順でText型からInteger型への変更も可能だと思います。

Moduleを作ろうかと考えましたが、Field Type毎にシリアライズされるデータが違ったり、生成されるTableの構造が違ったりで、様々なField Typeに対応させるのはむりがあるなと、1分ほど考えてやめました。
Drupalでのサイト構築はすごく捗るのですが、Drupalでの構築後の変更はなかなか骨の折れる仕事です。構築前に設計段階で、数値型が良いとされる場合フィールドに対しても、金額など明確に数値である必要が有る場合を除き、Text型を使ったほうが汎用性があり良いかもしれませんね。(例えば、郵便番号の場合日本では数値のみですが海外ではアルファベットが入る。構築当初10進数の仕様だったが、後の拡張で16進数の文字やA-Zの文字列も使う必要がでてきた。等)

参考にしたサイト


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です