D8 visual

Drupal 8 migration strategies

Kevin VB
Drupal 8

Content is always one of the most important parts of a website. After all, the internet was designed for information sharing. As a result, upgrading to a new CMS implies the migration of content in some form or another. Taking this into account in the early stages is crucial when considering and preparing a CMS upgrade.
The Drupal community is very aware of content migration as a key success factor. Therefore, Drupal’s latest version (D8) has the
migrate module included in its core. This key functionality allows you to upgrade from an older Drupal version to Drupal 8, using a few simple configuration steps. Below, I will explain how this works and put forward a few alternatives for custom migrations. A Dutch translation of this article is available here.

 

Why should you migrate to Drupal 8?

Site speed is not only important for SEO; it also affects your visitors’ browsing time and exit rate. Drupal 8 comes with an improved caching system that makes Drupal fly - all while taking into account content modification. There are no more endless waits for caches to invalidate, thanks to the real-time cache invalidation using cache tags.
Another reason for migration is the Drupal community. Plenty of features are available to integrate in your own site for free, which in turn enables you to spend time and money on other things. The community also keeps an eye on continuous improvements to the existing code. Drupal 8 is a great example of this, with its foundations in the Symfony2 framework. Everything in D8 has been standardised in such a way that maintenance is a lot easier and time-effective.
Let there be no doubt that migrating to Drupal 8 is an excellent long-term move!

 

How exactly should I migrate to Drupal 8?

You can use the Drupal migrate module that is included in core to upgrade from an older Drupal version to Drupal 8. Make sure to install and enable required modules first.
An example: if your site uses special field types, those modules should also be installed in your new Drupal 8 website. When you’re done configuring your site, you just need to enable the following modules:

  • Migrate
  • Migrate Drupal
  • Migrate Drupal UI

This last module will direct you to a configuration page, where you can start the actual migration. Simply enter the database information from your existing Drupal site and let Drupal review the upgrade.

The review will give you a list of available upgrade paths, next to a list of modules that are currently missing. If you’re happy about the review, you can choose to start the upgrade. Drupal will start importing content, users and taxonomies into your Drupal 8 website. Be aware that a rollback mechanism through the UI of Drupal is not available at this time. Since the Drupal core migrate is built to support a certain number of cases, it is possible that your site is too complicated to import correctly with the Migrate Drupal module. Sometimes, writing a customised migration is a better approach.
 

How to write a customized migration?

In most cases, the Migrate Drupal module will result in a reinstall of your Drupal website because some parts have been imported in the wrong way. You can opt to play things safe and write the migration yourself.
Writing a migration in Drupal 8 is done with the Migrate Plus module. This module allows you to create a new Migration entity. Those entities are created in YAML.

# Migration configuration for News content.
id: news_node
label: News Content Type
migration_group: demo_news
source:
 plugin: news_node
destination:
 plugin: entity:node
process:
 type:
   plugin: default_value
   default_value: news
 langcode:
   plugin: default_value
   source: language_code
   default_value: nl
 title: post_title
 field_title: post_title
 path: path
field_tags:
 plugin: migration
 migration:
   - news_terms
 source: tags_terms

migration_dependencies:
 required:
   - news_terms

Example of a Migration entity: migrate_plus.migration.news_node.yml

Each migration entity can belong to a Migration Group entity and is defined in YAML with the key ‘migrate_group’. A whole group of migrations can be imported or rolled back at once with drush by installing the Migrate Tools module.

  • drush mi --group=”demo_news” Import all migration in group demo_news
  • drush mr --group=”demo_news” Rollback all migrations in group demo_news

 

The main key of a migration is a Drupal 8 plugin that tells the migration where the source information comes from. There are plenty of base source plugins available for Drupal 8.

  • SqlBase - in Drupal Core: lets you migrate from an SQL source.
  • URL - in Migrate Plus: lets you migrate from a URL which can return JSON, XML, SOAP.
  • CSV - in Migrate Source CSV: lets you migrate from a CSV source file.
  • Spreadsheet - in Migrate Spreadsheet: lets you migrate from a csv, xls or xlsx source file.

If this does not suffice, you can start from your own source that extends from the SourcePluginBase class.

We extended the SqlBase source for our news_node source plugin.

public function query() {
 $query = $this->select('post', 'p');
 $query->fields('p', [
   'ID',
   'post_title',
   'post_name',
   'post_date',
 ]);
 $query->condition('p.type', 'news');
 return $query;
}

Query function in news_node source.

The query function returns a Select object with the information needed during the migration. This object will be the source for our migration.
Next we need to tell the migration which fields we want to map to the migration. This is done with the fields method.

public function fields() {
 $fields = [
   'post_title' => $this->t('The Post Node title'),
   'post_date' => $this->t('The Post creation time'),

   // ...
 ];

 return $fields;
}

In Drupal 7 we used prepareRow to provide field information that couldn’t be selected with a single query. In Drupal 8, this function is also available. In our example we fetch a teaser image and then add the file ID and file alt to the migration source.

public function prepareRow(Row $row) {
// Find related teaser attachment image.
$file = $this->getTeaserImage($content_id);

// Set a new property file_id.
$row->setSourceProperty('file_id', $file['id']);
$row->setSourceProperty('file_alt', $file['alt']);
return parent::prepareRow($row);
}

Add extra information to the migration in preparerow.

When we go back to the YAML confirmation of our migration entity, we see that there is also a destination key configured. In most cases this will be an entity:entity_type destination plugin. Migrate will then automatically create entities of the configured type. In our example, new nodes will be created. If needed, you can also simply create a new destination plugin, which performs extra actions during the import function.

 

The progress key in our configuration defines the field value mapping. It contains a mapping of keys and values where the key is the Drupal field name and the value is the source field name. In some cases, like ‘type’ or ‘language’, we use a default_value plugin which allows us to set the value of the field to a fixed value. In our example, we are creating new nodes of type news in Dutch.

In some cases, the source value comes from another migration. In our example the value of ‘field_tags’ comes from another migration, this is defined by using the ‘migration’ plugin and then specify the migration(s) in which the value is migrated. Whenever such migration dependent fields are presents an extra key ‘migration dependencies’ is necessary. This is an array of migrations which needs to run first.


I hope this post has helped you to provide some insight in migrating your website from D7 to D8! As always, you can reach out to me and the rest of the team via our website.
 

Subscribe to our newsletter

Recommended articles
Drupal 8 migration strategies
Custom REST resources
Drupal 8 config management (part 1)
Dropsolid at Drupal Europe
Multiple Drush versions on one system

Reacties

transform node links in body
Hello,

I'm looking for solution to transform links, saved in body field by content menager, relevant to current migrated content. E.g. :
.... some content <a href="node/[d7_nid]">Link</a> some content ...
SHOULD TRANSFORM TO:
.... some content <a href="node/[d8_nid]">Link</a> some content ...

When I was migrating from D6 to D7 there was Migration::handleSourceMigration function which allows you to reach this goal.

Thank you for any clues. Michael.

Add new comment