Migrate Drupal 7 to Drupal 8 / 9 using aliases
設定來源資料庫
<site>\sites\default\Settings.php
// Database entry needed by Migrate D7
// This is the source database connection d7. needs 'upgrade' key
$databases['upgrade']['default'] = array (
'database' => 'drupal7',
'username' => 'drupal7',
'password' => '$webdbpw',(1)
'prefix' => '',
'host' => 'localhost',
'port' => '3306',
'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
'driver' => 'mysql',
);
// Database entry needed by by Migrate D7 (2)
// This is the target database connection d8 needs 'migrate' key
$databases['migrate']['default'] = array (
'database' => 'd7d8db',
'username' => 'd7d8db',
'password' => '$webdbpw',(1)
'prefix' => '',
'host' => 'localhost',
'port' => '3306',
'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
'driver' => 'mysql',
);
1 | $webdbpw 修改為實際密碼。 |
2 | 沒有作用,但必須有該資料庫,執行遷移時才不會出錯! |
建立 d7d8db 資料庫
mysql -uroot -p$mysqlpw --host=localhost --port=3306 --protocol=tcp -N<<EOF
drop database if exists d7d8db;
create database d7d8db;
grant all privileges on d7d8db.* to 'd7d8db'@'localhost' identified by '$webdbpw';
use mysql;
update user set plugin='mysql_native_password' where user='d7d8db';
EOF
migrate_d7alias
/var/www/drupal/modules/migrate_d7alias 目錄結構
migrate_d7alias ├── modules │ ├── migrate_d7_guide │ │ ├── config │ │ │ └─ install │ │ │ ├─ migrate_plus.migration_group.d7_guide.yml │ │ │ ├─ migrate_plus.migration.d7_guide_base.yml │ │ │ └─ migrate_plus.migration.d7_guide_trans.yml │ │ ├─ migrate_d7_guide.info.yml │ │ └─ migrate_d7_guide.install │ └─ migrate_d7_others (1) ├── src │ └─ Plugin │ └─ migrate │ └─ source │ └─ D7alias.php └─ migrate_d7alias.info.yml
1 | 若要遷移另一組不同的 Content types ,migrate_d7_guide 複製至 migrate_d7_others,將 migrate_d7_others 檔案及內容的 guide 改成 others ,Guide 改成 Others 。 |
migrate_d7alias/modules/migrate_d7_guide/config/install/migrate_plus.migration_group.d7_guide.yml
name: Migrate D7 Alias
type: module
description: Migrate D7 Alias to D8
core_version_requirement: ^8.8 || ^9
package: Custom
dependencies:
- migrate_plus
- migrate_drupal
migrate_d7alias/modules/migrate_d7_guide/config/install/migrate_plus.migration.d7_guide_base.yml
langcode: en
status: true
dependencies: { }
id: d7_guide_base
migration_tags: null
migration_group: d7_guide
label: Guide base
source:
plugin: migrate_d7alias
node_type: guide (1)
destination:
plugin: 'entity:node'
default_bundle: guide (2)
process:
nid: nid
langcode: language
title: title
status: status
created: created
changed: changed
promote: promote
field_url: alias (3)
sticky: sticky
body:
plugin: sub_process
source: body
process:
value: value
format:
plugin: default_value
default_value: full_html (4)
path/pathauto:
plugin: default_value
default_value: 0 # Disable pathauto (5)
path/alias: alias # alias to path_alias
1 | guide 為 D7 的 Content types (Machine name)。 |
2 | guide 為 D8 的 Content types (Machine name)。 |
3 | 假設 D8 的 guide 中有 field_url 欄位,將 D7 的 alias 填入該欄位。註: 沒有該欄位並不會引發錯誤。 |
4 | 指定 Text formats and editors (<site>/admin/config/content/formats) 中的 Machine name: full_html 。 |
5 | 取消 Pathauto 自動產生網址。註: 沒有安裝 Pathauto 並不會引發錯誤。 |
migrate_d7alias/modules/migrate_d7_guide/config/install/migrate_plus.migrate_plus.migration.d7_guide_trans.yml
langcode: en
status: true
dependencies: { }
id: d7_guide_trans
migration_tags: null
migration_group: d7_guide
label: Guide translations
source:
plugin: migrate_d7alias
node_type: guide
translations: true
destination:
plugin: 'entity:node'
default_bundle: guide
translations: true
process:
nid:
plugin: migration_lookup
source: tnid
migration: d7_guide_base
langcode: language
title: title
status: status
created: created
changed: changed
promote: promote
sticky: sticky
body:
plugin: sub_process
source: body
process:
value: value
format:
plugin: default_value
default_value: full_html
path/pathauto:
plugin: default_value
default_value: 0 # Disable pathauto
path/alias: alias # alias to path_alias
migration_dependencies:
required:
- d7_guide_base
migrate_d7alias/modules/migrate_d7_guide/migrate_d7_guide.info.yml
name: Migrate D7 Guide
type: module
description: Migrate D7 Guide to D8
core_version_requirement: ^8.8 || ^9
package: Custom
dependencies:
- migrate_d7alias
migrate_d7alias/modules/migrate_d7_guide/migrate_d7_guide.install
<?php
/**
* @file
* Contains install and uninstall hooks.
*/
/**
* Implements hook_uninstall().
*/
function migrate_d7_guide_uninstall() {
\Drupal::entityTypeManager()->getStorage('migration')->load('d7_guide_base')->delete();
\Drupal::entityTypeManager()->getStorage('migration')->load('d7_guide_trans')->delete();
\Drupal::entityTypeManager()->getStorage('migration_group')->load('d7_guide')->delete();
}
migrate_d7alias/src/Plugin/migrate/source/D7alias.php
<?php
/**
* @file
* Contains \Drupal\migrate_d7alias\Plugin\migrate\source\D7alias.
*/
namespace Drupal\migrate_d7alias\Plugin\migrate\source;
use Drupal\migrate\Row;
use Drupal\node\Plugin\migrate\source\d7\Node;
/**
* Migration Source for fruit nodes
*
* @MigrateSource(
* id = "migrate_d7alias"
* )
*/
class D7alias extends Node
{
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row)
{
// Include path alias.
$nid = $row->getSourceProperty('nid');
$query = $this->select('url_alias', 'ua')->fields('ua', ['alias']);
$query->condition('ua.source', 'node/' . $nid);
$alias = $query->execute()->fetchField();
if (!empty($alias)) {
$row->setSourceProperty('alias', '/' . $alias);
}
return parent::prepareRow($row);
}
}
migrate_d7alias/migrate_d7alias.info.yml
name: Migrate D7 Alias
type: module
description: Migrate D7 Alias to D8
core_version_requirement: ^8.8 || ^9
package: Custom
dependencies:
- migrate_plus
- migrate_drupal
安裝及遷移
安裝 migrate_d7alias
site=drupal
cd /var/www/$site
composer require drupal/migrate_tools drupal/migrate_plus
drush en migrate_tools -y
drush en migrate_d7alias migrate_d7_guide -y
# drush en migrate_d7_others -y
chwww $site
修改 d7_guide_base.yml d7_guide_trans.yml 後,需要重裝
drush pmu migrate_d7_guide
drush en migrate_d7_guide
遷移 D7
site=drupal
cd /var/www/$site
drush migrate:status
# ---------------------------- ----------------
# Group Migration ID
# ---------------------------- ----------------
# D7 guide imports (d7_guide) d7_guide_base
# D7 guide imports (d7_guide) d7_guide_trans
drush state:set system.maintenance_mode 1 --input-format=integer
# drush cr
# 將 link__uri 修改為 fake,避免刪除 node 時同時刪除 menu。
drush sql-query "update menu_link_content_data set link__uri=concat(link__uri,'-fake') where link__uri not like '%-fake'"
drush sql-query "update menu_link_content_field_revision set link__uri=concat(link__uri,'-fake') where link__uri not like '%-fake'"
drush cr
drush migrate:rollback --group=d7_guide (1)
drush migrate-import --group=d7_guide --update
# 將 link__uri 回復
drush sql-query "update menu_link_content_data set link__uri=replace(link__uri,'-fake','')"
drush sql-query "update menu_link_content_field_revision set link__uri=replace(link__uri,'-fake','')"
# drush cr
# 重建索引
drupal cron:execute
drush state:set system.maintenance_mode 0 --input-format=integer
drush cr
1 | Migrate 前先刪除全部,避免出現重複文章。 |
已將 D7 的 alias 一併遷移至 D8,照理說不會裝 Pathauto 才對。如果有安裝,在執行前必須將 Pathauto patterns 禁能,否則會出錯。
如錯誤可能為 Migration d7_guide_trans is busy with another operation: Importing
。
出錯時執行下列
drush migrate:stop d7_guide_base
drush migrate:stop d7_guide_trans
drush migrate:reset-status d7_guide_trans
drush migrate:reset-status d7_guide_base
- Reference
-
Migrating Content Translated with "Content Translation" from Drupal 7 to Drupal 8 | Evolving Web Blog
Migrating Drupal 7 Page, Article to Drupal 8 Page, Article | Migrate API | Drupal guide on Drupal.org
Drupal to Drupal 8 via Migrate API | Chapter Three
Drupal8 Migrate API, Migrating Nodes From Drupal7 – Part 1 – TA Digital Labs
Node complete creates new nodes when used for incremental migrations (Drupal 9)