When migrating from Drupal 7 to Drupal 8, it is important to remember to migrate over the redirects as well. Without the migrations users will not find your content if for example: the redirect was shared on social media. Using the Migrate Plus module, it is quite simple to write a migration for the redirects. The Migrate Plus module contains some good examples on how to get started writing your custom migrations.

Write your node migrations

I am going to assume that you have written migration for some content types and have the group already written. Once those migrations have been written, in your database should now be a migrate_map_{name}_{type} table. This is where we will be able to find the imported node’s new id which will be necessary for importing the redirects.

Write the yml file for redirect migrations

For example, let’s say we have a module called blog_migrations. In that module we have a group for blog and a migration for a news and opinion content type. Inside the config/install directory add a new yml file called migrate_plus.migration.blog_redirect.yml where blog is the name of the group being migrated. This file will give an id, label, and the process to use for the migration.

id: blog_redirect
label: Path Redirect
migration_group: blog
migration_tags:
  - Drupal 7
source:
  # This is the id of the source we will add. That will live
  # in `/src/Plugin/migrate/source`.
  plugin: blog_redirect
  key: blog
process:
  rid: rid
  uid: uid
  redirect_source/path: source
  redirect_source/query:
   # `RedirectSourceQuery.php` is the process plugin to use.
   plugin: d7_redirect_source_query
   source: source_options
  redirect_redirect/uri:
    # `PathRedirect.php` is the process plugin to use.
    plugin: d7_path_redirect
    source:
      - redirect
      - redirect_options
  language:
    plugin: default_value
    source: language
    default_value: und
  status_code: status_code
destination:
  plugin: entity:redirect

Write the migrate source

Create the file BlogRedirect.php in the module’s src/Plugin/migrate/source folder.

<?php

namespace Drupal\apa_migrate\Plugin\migrate\source;

use Drupal\Core\Database\Database;
use Drupal\migrate\Row;
use Drupal\redirect\Plugin\migrate\source\d7\PathRedirect;

/**
 * Drupal 7 path redirect source from database.
 *
 * @MigrateSource(
 *  id = "blog_redirect"
 * )
 */
class BlogRedirect extends PathRedirect {

  /**
   * {@inheritdoc}
   */
  public function query() {
    // Select path redirects.
    $query = $this->select('redirect', 'p')->fields('p')
      ->condition('redirect', '%user%', 'NOT LIKE');

    return $query;
  }

  /**
   * {@inheritdoc}
   */
  public function prepareRow(Row $row) {
    // Get the current status code and set it.
    $current_status_code = $row->getSourceProperty('status_code');
    $status_code = $current_status_code != 0 ? $current_status_code : 301;
    $row->setSourceProperty('status_code', $status_code);

    $current_redirect = $row->getSourceProperty('redirect');
    $explode_current_redirect = explode("/", $current_redirect);

    $map_blog_array = array(
      'news',
      'opinion'
    );
   // Determine if the path is redirected to a /node/{id} path.
    if ($explode_current_redirect[0] == 'node') {
      // Determine the content type for the node.
      $resource_type = $this->getDatabase()
        ->select('node', 'n')
        ->fields('n', ['type'])
        ->condition('nid', $explode_current_redirect[1])
        ->execute()
        ->fetchField();

      // Check that the type is in the node types we want to migrate for.
      if (in_array($resource_type, $map_apa_array)) {
        // Gather the information about where the node is now.
        $new_node_id = Database::getConnection('default', 'default')
          ->select('migrate_map_apa_' . $resource_type, 'm')
          ->fields('m', ['destid1'])
          ->condition('sourceid1', $explode_current_redirect[1])
          ->execute()
          ->fetchField();

        // Set the new redirect.
        $new_redirect = 'node/' . $new_node_id;
        $row->setSourceProperty('redirect', $new_redirect);
      }
    }
  }
}

Run the migrations

Using the config_devel module, now import the configuration into active store to be able to run the migration using:

drush cdi1 /modules/custom/blog_migration/config/install/migrate_plus.migration.blog_redirect.yml

Then run the actual migration:

drush mi blog_redirect

After running that you should now have migrated the two content type’s redirects with the new node id they were given! Any questions, let us know in the comments below.