drupal-migration について
drupal-migration は、Drupal の Migrate API を使う開発者向けのスキルです。Drupal 7 の移行、CSV・JSON/API のインポート、カスタムプラグイン、Drush による実行とデバッグを扱います。
主な機能
- 01Drupal 7 から 10/11 への移行ガイド
- 02CSV・JSON/API データのインポート
- 03YAML 移行マッピングのパターン
- 04カスタムソース・プロセスプラグイン
- 05Drush による実行とデバッグ
活用シーン
- 01Drupal 7 サイトのアップグレード計画
- 02CSV や API からの商品・ユーザーデータの取り込み
- 03カスタム移行変換の構築
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ madsnorgaard/ drupal-agent-resources --skill drupal-migrationインストール後、Claude Code で/drupal-migrationを入力して読み込まれたか確認します。
詳細
Drupal 移行エキスパート
Drupal の Migrate API に精通したエキスパートとして、D7 から D10/D11 への移行、CSV のインポート、カスタムデータの移行を支援します。
必須モジュール
# Core migration modules
drush en migrate migrate_drupal migrate_drupal_ui
# Contrib essentials
composer require drupal/migrate_plus drupal/migrate_tools drupal/migrate_file
drush en migrate_plus migrate_tools migrate_file
| モジュール | 用途 |
|---|---|
migrate | コアの移行フレームワーク |
migrate_drupal | D6/D7 の移行サポート |
migrate_drupal_ui | ブラウザー上で操作できる移行ウィザード |
migrate_plus | 設定ベースの移行、追加のソースプラグイン |
migrate_tools | 移行用の Drush コマンド |
migrate_file | ファイルの移行処理 |
移行アーキテクチャ
移行 YAML の構造
# migrations/migrate_plus.migration.my_migration.yml
id: my_migration
label: 'My Migration'
migration_group: my_group
source:
plugin: source_plugin_name
# Source configuration
process:
# Field mappings
destination_field: source_field
destination:
plugin: 'entity:node'
default_bundle: article
migration_dependencies:
required:
- other_migration
主な構成要素
- ソース - データの取得元(D7 データベース、CSV、JSON API)
- プロセス - ソースと移行先の間でデータを変換します
- 移行先 - データの移行先(ノード、ユーザー、タクソノミーターム)
D7 から D10 への移行
データベース接続の設定
// settings.php
$databases['migrate']['default'] = [
'driver' => 'mysql',
'database' => 'drupal7_db',
'username' => 'db_user',
'password' => 'db_pass',
'host' => 'localhost',
'prefix' => '',
];
UI を使用する
drush en migrate_drupal_ui
# Visit /upgrade to use wizard
Drush を使用する(推奨)
# Generate migrations from D7
drush migrate:upgrade --legacy-db-key=migrate --configure-only
# List generated migrations
drush migrate:status
# Run all migrations
drush migrate:import --all
# Run specific migration
drush migrate:import upgrade_d7_node_article
# Rollback
drush migrate:rollback upgrade_d7_node_article
よくある D7 移行のカスタマイズ
生成された移行をカスタム YAML でオーバーライドします。
# migrations/migrate_plus.migration.upgrade_d7_node_article.yml
id: upgrade_d7_node_article
label: 'Article nodes from D7'
migration_group: migrate_drupal_7
source:
plugin: d7_node
node_type: article
process:
type:
plugin: default_value
default_value: article
title: title
uid:
plugin: migration_lookup
migration: upgrade_d7_user
source: uid
body:
plugin: sub_process
source: body
process:
value: value
format:
plugin: static_map
source: format
map:
full_html: full_html
filtered_html: basic_html
default_value: basic_html
field_image:
plugin: migration_lookup
migration: upgrade_d7_file
source: field_image/0/fid
destination:
plugin: 'entity:node'
default_bundle: article
migration_dependencies:
required:
- upgrade_d7_user
- upgrade_d7_file
CSV の移行
ソースプラグインの設定
# migrations/migrate_plus.migration.import_products.yml
id: import_products
label: 'Import products from CSV'
migration_group: imports
source:
plugin: csv
path: 'modules/custom/my_module/data/products.csv'
ids:
- sku
header_row_count: 1
# Optionally define columns explicitly
column_names:
0:
sku: 'Product SKU'
1:
name: 'Product Name'
2:
price: 'Price'
3:
category: 'Category'
process:
type:
plugin: default_value
default_value: product
title: name
field_sku: sku
field_price: price
field_category:
plugin: entity_lookup
source: category
entity_type: taxonomy_term
bundle: product_categories
bundle_key: vid
value_key: name
destination:
plugin: 'entity:node'
default_bundle: product
CSV 移行の実行
# Import
drush migrate:import import_products
# Update existing records
drush migrate:import import_products --update
# Reset status if stuck
drush migrate:reset-status import_products
JSON/API の移行
HTTP JSON ソース
id: import_api_users
label: 'Import users from API'
source:
plugin: url
data_fetcher_plugin: http
data_parser_plugin: json
urls:
- 'https://api.example.com/users'
item_selector: data
ids:
id:
type: integer
fields:
- name: id
selector: id
- name: email
selector: email
- name: full_name
selector: attributes/name
process:
name: full_name
mail: email
init: email
status:
plugin: default_value
default_value: 1
destination:
plugin: 'entity:user'
よく使われるプロセスプラグイン
基本的な変換
process:
# Direct mapping
title: source_title
# Default value
status:
plugin: default_value
default_value: 1
# Static mapping
field_type:
plugin: static_map
source: type
map:
old_type_1: new_type_1
old_type_2: new_type_2
default_value: default_type
# Concatenate
title:
plugin: concat
source:
- first_name
- last_name
delimiter: ' '
# Substring
field_summary:
plugin: substr
source: body
start: 0
length: 200
エンティティ参照
process:
# Migration lookup (referenced entity was migrated)
uid:
plugin: migration_lookup
migration: users
source: author_id
# Entity lookup (entity already exists)
field_category:
plugin: entity_lookup
source: category_name
entity_type: taxonomy_term
bundle: categories
bundle_key: vid
value_key: name
# Entity generate (create if not exists)
field_tags:
plugin: entity_generate
source: tags
entity_type: taxonomy_term
bundle: tags
bundle_key: vid
value_key: name
複数の値
process:
# Handle multiple values
field_tags:
plugin: sub_process
source: tags
process:
target_id:
plugin: entity_generate
source: name
entity_type: taxonomy_term
bundle: tags
value_key: name
# Explode string to array
field_keywords:
- plugin: explode
source: keywords
delimiter: ','
- plugin: entity_generate
entity_type: taxonomy_term
bundle: keywords
value_key: name
条件付き処理
process:
# Skip if empty
field_image:
plugin: skip_on_empty
method: process
source: image_url
# Skip row if condition
pseudo_skip:
plugin: skip_on_value
source: status
method: row
value: 'draft'
カスタムソースプラグイン
<?php
declare(strict_types=1);
namespace Drupal\my_module\Plugin\migrate\source;
use Drupal\migrate\Attribute\MigrateSource;
use Drupal\migrate\Plugin\migrate\source\SqlBase;
use Drupal\migrate\Row;
/**
* Custom source for legacy products.
*/
#[MigrateSource(
id: 'legacy_products',
source_module: 'my_module',
)]
class LegacyProducts extends SqlBase {
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('legacy_products', 'p');
$query->fields('p', ['id', 'name', 'price', 'description']);
$query->condition('p.status', 'active');
$query->orderBy('p.id');
return $query;
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'id' => $this->t('Product ID'),
'name' => $this->t('Product name'),
'price' => $this->t('Price'),
'description' => $this->t('Description'),
];
}
/**
* {@inheritdoc}
*/
public function getIds() {
return [
'id' => [
'type' => 'integer',
'alias' => 'p',
],
];
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
// Add computed fields or modify data
$price = $row->getSourceProperty('price');
$row->setSourceProperty('price_with_tax', $price * 1.21);
return parent::prepareRow($row);
}
}
カスタムプロセスプラグイン
<?php
declare(strict_types=1);
namespace Drupal\my_module\Plugin\migrate\process;
use Drupal\migrate\Attribute\MigrateProcess;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
/**
* Converts price from cents to decimal.
*
* Example usage:
* @code
* process:
* field_price:
* plugin: cents_to_decimal
* source: price_cents
* @endcode
*/
#[MigrateProcess(id: 'cents_to_decimal')]
class CentsToDecimal extends ProcessPluginBase {
/**
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
if (empty($value) || !is_numeric($value)) {
return NULL;
}
return number_format((float) $value / 100, 2, '.', '');
}
}
Drush コマンドのリファレンス
# List all migrations
drush migrate:status
# Run migration
drush migrate:import migration_id
# Run with options
drush migrate:import migration_id --limit=100
drush migrate:import migration_id --update
drush migrate:import migration_id --sync
# Rollback
drush migrate:rollback migration_id
# Reset stuck migration
drush migrate:reset-status migration_id
# Stop running migration
drush migrate:stop migration_id
# Show messages/errors
drush migrate:messages migration_id
移行のデバッグ
詳細出力を有効にする
drush migrate:import migration_id -vvv
移行ステータスの確認
# Add to migration YAML
migration_tags:
- debug
プロセス結果のログ記録
// In custom process plugin
\Drupal::logger('my_migration')->notice('Processing: @value', ['@value' => $value]);
よくある問題
「移行は使用中です」:
drush migrate:reset-status migration_id
メモリエラー:
drush migrate:import migration_id --limit=500
# Process in batches
依存関係の不足:
YAML の migration_dependencies が実際の移行 ID と一致していることを確認してください。
ベストプラクティス
- 関連する移行を整理するため、必ず移行グループを使用します
- 正しい順序を確保するため、
migration_dependenciesを設定します - 全件をインポートする前に、
--limit=10でテストします - 更新した移行を再実行するには、
--updateを使用します - 移行の検証が完了するまで、ソースデータを保持します
- 移行 YAML のコメントにフィールドマッピングを記録します
- 本番環境への移行前にロールバック計画を作成します
- 大規模な移行では、メモリ使用量を監視します
移行モジュールの構造
my_migration/
├── my_migration.info.yml
├── my_migration.module
├── config/
│ └── install/
│ ├── migrate_plus.migration_group.my_group.yml
│ ├── migrate_plus.migration.users.yml
│ └── migrate_plus.migration.content.yml
├── src/
│ └── Plugin/
│ └── migrate/
│ ├── source/
│ │ └── LegacyProducts.php
│ └── process/
│ └── CentsToDecimal.php
└── data/
└── import.csv
参考資料
コメント
Markdown 対応