Drupal Migrate

Oct 31, 2012

Wat is Drupal migrate? Volgens de documentatie: http://drupal.org/project/migrate

The migrate module provides a flexible framework for migrating content into Drupal from other sources (e.g., when converting a web site from another CMS to Drupal). Out-of-the-box, support for creating core Drupal objects such as nodes, users, files, terms, and comments are included - it can easily be extended for migrating other kinds of content.

Ik ga er voor de gemakkelijkheid van uit dat je al bekend bent met drush, drush is niet essentieel voor migrate maar het maakt het wel een heel pak makkelijker. Sowieso is drush wel erg handig voor drupal-ontwikkeling.

Hoe ga ik te werk?

Na de migrate-module geinstalleerd te hebben maak je een eigen, nieuwe module aan. In dit geval heet deze: import_csv_files. Dit is de mappenstructuur van deze eenvoudige module.

import_csv_files/import_csv_files.module
import_csv_files/import_csv_files.info
import_csv_files/includes/importer_table_a.inc

We beginnen bij het import_csv_files.info bestand.

name = "Example table importer"
description = "Module to migrate CSV files to drupal"
package = "Development"
core = 7.x

dependencies[]= migrate
dependencies[]= field
dependencies[]= number
dependencies[]= text

files[]= includes/importer_table_a.inc

Dit zou allemaal duidelijk moeten zijn. Je geeft de bestanden via de .info-file mee in plaats van via een module_load_include.

Het import_csv_files.module bestand is ook erg basic:

<?php

/**
 * Implements hook_migrate_api().
 */
function import_csv_files_migrate_api() {
  $api = array(
    'api' => 2,
  );

  return $api;
}

Nu komt het belangrijkste bestand, hetgene waar de importer-class zelf in zit. Je kan dit natuurlijk ook gewoon rechtstreeks in de .module zetten, maar omdat ik meerdere importers nodig had voor dit project heb ik er voor gekozen om elke class in zijn eigen bestand neer te zetten.

Alle bestanden gaan starten met een soortgelijke class-definitie. Waarbij in dit geval ImportCSV de naam is van de migration, vergeet de Migration bij de classname niet!

<?php

class ImportCSVMigration extends Migration {

    public function __construct() {
      parent::__construct(MigrateGroup::getInstance('testInstance'));

      // Define CSV source.
      $this->source = new MigrateSourceCSV(
        'test.csv',
        array(),
        array(
          'header_rows' => 1,
          'delimiter' => ';'
        )
      );

      // Add destination table.
      $this->destination = new MigrateDestinationTable('test_table');

      // Add mapping to primary key. The array key is CSV key.
      $this->map = new MigrateSQLMap(
        $this->machineName,
        array(
          'KEY' => array(
            'type' => 'int',
            'unsigned' => TRUE,
            'not null' => TRUE,
          ),
        ),
        MigrateDestinationTable::getKeySchema($this->table)
      );

      // Add relevant mapping.
      $this->addFieldMapping('external_key', 'KEY');
      $this->addFieldMapping('title', 'NAME');
      $this->addFieldMapping('description', 'DESCR');
      $this->addFieldMapping('id')->defaultValue(NULL); # auto increment
    }
}

We vullen hier dus een tabel test_table die de velden: id, title, description en external_key heeft.

Nu clearen we de drupal cache via drush cc all en vervolgens zorgen we dat migrate de nieuwe class herkent via drush mar (migrate-autoregister). Om dat te testen kan je naar de migrate-gui kijken of via drush ms (migrate-status).

Als er geen fouten zijn kan je nu via drush mi ImportCSV --limit="1" een enkele regel van de CSV importeren in de database. Bij grotere bestanden kan je best met een kleine limit werken tot alle fouten er uit zijn en dan via drush mr ImportCSV een rollback uitvoeren voor je alles importeerd via drush mi ImportCSV. Ook handig bij het importeren van grotere bestanden is de optie --feedback, feedback kan een status-update geven bij een aantal seconden of items, op die manier heb je een beter idee van hoe de import-actie verloopt. Bijvoorbeeld zo: drush mi ImportCSV --feedback="1000 items".

Indien je begonnen migratie wil stoppen kan dat via drush mst ImportCSV wat de huige actie stopt en dan via drush mrs ImportCSV de migratie terug op “idle” zetten.

Je kan ook altijd via drush ms kijken wat de status is van alle migrations die geregistreerd zijn.

Om alle drush commando’s te bekijken waarmee je migrate kan aansturen helpt volgend commando: drush help --filter=migrate.