Migrating Your Data from Drupal 7 to Drupal 10: Customizing the generated migration Migration How-to: #11

Migrate Plus configuration entities

The custom installation profile is named tag1_profile and it is modeled after the minimal installation profile provided by Drupal core. In our example, sticking with minimal would probably suffice. But in large projects, a custom installation profile can be used to store code related to the site itself. One key assumption of our example project is that the site can be reinstalled at any point using the exported configuration.

Image from Pixabay
Note: At the time of this writing, a new recipes API was recently introduced to Drupal core in version 10.3.0. Recipes can be used instead of installation profiles to fully configure a site. In our example project, we are sticking with installation profiles. Towards the end of the series, we will look at applying recipes to bring configuration into the site.
For reference, below is one way to manage migrations as configuration entities:
Let’s start with configuration entities. When using this approach, the Migrate Plus module is required. Notice that once the migrations are generated, the Migrate Upgrade module can be uninstalled as the migrations will live in the site’s active configuration: the database. When exported, the filename pattern will be migrate_plus.migration.MIGRATON_ID.yml.
Series Overview & ToC | Previous Article | Next Article – coming July 10th

# 1) Run the migration.

$ drush migrate:import upgrade_d7_user

# 2) Rollback migration because the expected results were not obtained.

$ drush migrate:rollback upgrade_d7_user

# 3) Change the migration definition file.

# 4) Rebuild caches for changes to be picked up.

$ drush cache:rebuild

# 5) Run the migration again.

$ drush migrate:import upgrade_d7_user

For now, the final version of the migration file should look like this:
The tag1_migration_config module will contain all the configuration migrations as core plugins. In fact, this is a submodule of the tag1_migration module. As said before, it is convenient to have all migration related code in one location. Remember that not all configuration will come from a migration. The tag1_migration_config could be removed after the migrated configuration makes its way to the config_sync_directory folder. Instead, I prefer to uninstall the module but keep the code around to have a reference of how some of the configuration was generated via migrations.
While we progress through the examples, we will be migrating some configuration automatically and creating some manually. After every milestone, we will export the configuration. Then, we can use the drush site:install tag1_profile --existing-config command to get a fully configured site on top of which we can run content migrations.
After following the instructions in the previous article, you should have a file config/migrate_plus.migration.upgrade_d7_taxonomy_vocabulary.yml inside the Drupal 10 installation. The content of the file should look like:
The example project will use core migration plugins. However, the generated migrations use configuration entities. Let’s learn how to convert one approach to the other using the migration of taxonomy vocabularies.
In the previous article we learned how to generate migrations using the Migrate Upgrade module. As explained, those migrations are generated as configuration entities managed by the Migrate Plus module. Today, we will learn about using migration plugins provided by Drupal Core. After learning about these two methods of handling migrations, we will explain how the example project is set up to perform configuration and content migrations. Finally, we will take a glance at customizing the automatically generated migrations.
There are more changes that we could make. Most examples will make changes to the process section of the file. Some will also alter the source and destination sections. Each example will explain what customizations are needed and why we are making them.

$settings['container_yamls'][] = DRUPAL_ROOT . '/sites/development.services.yml';

$settings['cache']['bins']['discovery_migration'] = 'cache.backend.null';

This has many implications:

mkdir -p web/modules/custom/tag1_migration/tag1_migration_config/migrations/

mv config/migrate_plus.migration.upgrade_d7_taxonomy_vocabulary.yml web/modules/custom/tag1_migration/tag1_migration_config/migrations/upgrade_d7_taxonomy_vocabulary.yml

From config entities to core migration plugins
In recent years, this has been my preferred approach because making changes to the migration does not require updates to the site’s configuration. Also, clearing caches is arguably more straightforward than having to be cautious when syncing updates to migration configuration entities.
The tag1_migration module will contain all the content migrations as core plugins. If necessary, this module can be used to store custom source/process/destination migration plugins, hook implementations, registering event callbacks, and any other code related to migrating content entities.
Another way of handling migrations is using features provided by Drupal core out of the box. That is, using core migration plugins. When using this approach, the filename pattern is MIGRATION_ID.yml and the files are placed inside a migrations folder in your custom module. Rebuilding caches will apply the changes made to the migration files.
Now, let’s make changes to the file itself:
Helping you navigate the next steps on your Drupal Migration Journey
For reference, below is one way to manage migrations as core plugins:
The example project has three elements that will help organize the code related to the custom migration:

# 1) Run the migration.

$ drush migrate:import upgrade_d7_user

# 2) Rollback migration because the expected results were not obtained.

$ drush migrate:rollback upgrade_d7_user

# 3) Change the migration definition file in the "config/install" directory.

# 4) Sync configuration by folder using Drush.

$ drush config:import --partial --source="modules/custom/my_module/config/install"

# 5) Run the migration again.

$ drush migrate:import upgrade_d7_user

id: upgrade_d7_taxonomy_vocabulary
class: DrupalmigratePluginMigration
migration_tags:
- 'Drupal 7'
- Configuration
- taxonomy_vocabulary
- tag1_configuration
label: 'Taxonomy vocabularies'
source:
key: migrate
plugin: d7_taxonomy_vocabulary
process: ... # Redacted for brevity
destination:
plugin: 'entity:taxonomy_vocabulary'
migration_dependencies:
required: { }
optional: { }

The two primary ways of handling migrations in Drupal 10 are using Migrate Plus configuration entities and Drupal Core’s migration plugins. They differ in the filename pattern, the location where the migration files are placed, and how changes to the files are detected.
uuid: 79d5ff1c-7924-4508-99b5-ba0ad71d2960
langcode: en
status: true
dependencies: { }
id: upgrade_d7_taxonomy_vocabulary
class: DrupalmigratePluginMigration
field_plugin_method: null
cck_plugin_method: null
migration_tags:
- 'Drupal 7'
- Configuration
migration_group: migrate_drupal_7
label: 'Taxonomy vocabularies'
source:
plugin: d7_taxonomy_vocabulary
process:
vid:
-
plugin: make_unique_entity_field
source: machine_name
entity_type: taxonomy_vocabulary
field: vid
length: 30
migrated: true
label:
-
plugin: get
source: name
name:
-
plugin: get
source: name
description:
-
plugin: get
source: description
weight:
-
plugin: get
source: weight
destination:
plugin: 'entity:taxonomy_vocabulary'
migration_dependencies:
required: { }
optional: { }

It is useful to have all migration related functionality encapsulated in a custom module. When doing so, these migration files are placed inside the config/install folder of the custom module. When the module is enabled for the first time, the migrations will be copied to Drupal’s active configuration, which is the database. Further changes to the files inside the module will be ignored unless the configuration is synced again.

Similar Posts