Migrate Module: Migrate Terminology and Example

In the 1st post on the Migrate module I defined with Wikipedia’s help a migration of data, or Migration. The migrate module, a framework, lets us define our own migration between 2 systems.

Before we jump into a Migration its key to understand some general concepts and terminology when using the Migrate module.

Migrate Terminology

A Migration is defined typically by a PHP class you write. A migration class extends a base (or parent) Migrate class which automatically does much of the typical legwork in the final brief migration script I outlined in my first post. A migration class:

  • defines a source for the data, a MigrationSource. Many default migration sources are supplied by the Migrate framework. Examples of migration sources include CSV file data, XML file data, database connections, generic file listings.

  • defines a destination for data, referred to as the MigrateDestination instance. The Migrate framework supplies many default destinations for Migration data — these include Drupal content such as Nodes, Entities, Users and Files among others.

  • defines a mapping of source data to destination data referred to as a MigrateMap. Internally this is usually composed of a unique ID for each piece of data and is essentially a database table saying “source ID1 maps to Destination ID2”.

  • uses many MigrateFieldMapping’s instances to define how a source field schema is represented in the Destination for the data. Again, many default Drupal fields are supplied by the Migrate module by default and additional ones by the Migrate Extras module.

This may sound like a lot of work — but typically a single migration of data is not a ton of code. Being an Object Oriented framework all the architecture of a migration defined above is extensible as-needed by you using custom PHP code and registering new Migration Source classes, Destination classes, Field Mapping classes, etc.

If you’re not doing anything crazy with Migrate, you simply register your migration using hook_migrate_api in a custom module. If you need to extend Migrate you register additional classes (like a custom Drupal field) using hook_migrate_api.

An Example Migration

/*
 * Implements hook_migrate_api()
 *
 * Defines a migration for Pages of content, in a group (labeled) as "Move" in the Migration UI.
 */
function mymodule_migrate_api() {
  $api = array(
    'api' => 2,
    'groups' => array(
      'move' => array(
        'title' => t('Move Data from Src to Dest'),
      ),
    ),
    'migrations' => array(
      'MovePages' => array(
        'class_name' => 'MovePagesMigration',
        'group_name' => 'move',
      ),
    ),
  );
  return $api;
}

In a custom migration class included via the files[]= directive of your module.info file:

// This defines our custom migration. I think of this as 1 task.
class ExampleMigration extends Migration {
  public function __construct($arguments) {
    parent::__construct();
    // What is our legacy data? This example query defines what
    // legacy data we will move to the new Drupal website.
    $query = Database::getConnection('default', 'legacy_database')
             ->select('pages', 'p')
             ->fields('p', array('id', 'ptitle', 'pbody'));
    // The source used here is an SQL source, from the given query (of data).
    $this->source = new MigrateSourceSQL($query);
    // The destination here is a Drupal Node, specifically the bundle of 'page'.
    $this->destination = new MigrateDestinationNode('page');

    // This defines how each item of the Source is mapped to an instance of
    // the Destination data type. This allows us to rollback, or use a
    // highwater mark, or hash() value when performing migrations.
    $this->map = new MigrateSQLMap($this->machineName,
        array(
          'id' => array('type' => 'int',
                          'unsigned' => TRUE,
                          'not null' => TRUE,
                         )
        ),
        MigrateDestinationNode::getKeySchema()
      );

    // Lastly, any field mappings we need from the Source to Destination
    // are included here.
    $this->addFieldMapping('title', 'ptitle');
    $this->addFieldMapping('body', 'pbody');
  }
}

The above code registers a Migration in Drupal by implementing a hook. Then our custom code defines the logic of our migration. I hope the inline comments are satisfactory. With these 2 pieces of code we can run, and re-run our migrations as needed until they are perfect using either the Migrate UI or Drush.

This Migration class is very typical of any basic migration for Drupal content. Some thoughts regarding the Migrate module and its complexity you can ask yourself:

  • How much work would it be to change this from an SQL migration to a CSV migration?
  • How about adding additional fields to the migration?
  • This class based approach to migrations is easy to use and debug and (arguably) much more powerful than the example scripted migration in the 1st blog post; which would you like to maintain?
  • How reusable is this code (or code structure), how extendable? You can for instance create a base migration class that performs certain actions and override in child PHP migration classes.

Looking for quality Drupal Web Hosting? Look no further than Arvixe Web Hosting!

Tags: , , , , , | Posted under Drupal | RSS 2.0

Author Spotlight

David Gurba

David Gurba

I am a web programmer currently employed at UCSB. I have been developing web applications professionally for 8+ years now. For the last 5 years I’ve been actively developing websites primarily in PHP using Drupal. I have experience using LAMP and developing data driven websites for clients in aviation, higher education and e-commerce. If you’d like to contact me I can be reached at david.gurba@arvixe.com

Leave a Reply

Your email address will not be published. Required fields are marked *


6 − = 5

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>