I've used migrate 2 with a CSV source successfully before.
However, on what-seems-to-me a simpler project, I can't get the migration to register (migrate UI shows 'no migrations').
I've checked the .info and .module and csv path a million times for typos, and cleared the cache everytime, to no avail, and as such, am wondering if there are any debugging techniques for troubleshooting where the module goes awry. I can't get it to give me an error or anything. Just doesn't show.

info:

name = "Products Migrate"
description = "product migration data from csv"
package = "Development"

dependencies[] = migrate
dependencies[] = migrate_ui

files[] = my_module.migrate.inc

version = "7.x-1.0"
core = "7.x"

.module is just the stock code to set api level to 2
no .install file - I don't think I need one for a .csv import, do I? (I actually tried creating an install file in desperation, but to no avail)

.inc:

<?php
abstract class my_module_BasicMigration extends Migration {
  public function __construct() {
    // Always call the parent constructor first for basic setup
    parent::__construct();
  }
}

class my_module_ChairMigration extends my_module_BasicMigration {
  public function __construct() {
    parent::__construct();
    $this->description = t('Import Chairs into Product:Chair content type');
    $columns = array(
      // "Source": ('Fieldname', 'Description')
      0 => array('cat_number', t('Catalogue number (must be unique)')),
      1 => array('name', t('Product name')),
      2 => array('cat_page', t('Catalogue page')),
      3 => array('brief_desc', t('Brief Description')),
      4 => array('full_desc', t('Full description')),
      5 => array('designer', t('Designer')),
      6 => array('width', t('Width')),
      7 => array('depth', t('Depth')),
      8 => array('height', t('Height')),
      9 => array('seat_height', t('Seat Height')),
      10 => array('price', t('Price')),
      11 => array('stool-bool', t('Is it a stool'))
    );
    $this->source = new MigrateSourceCSV(DRUPAL_ROOT . '/' . drupal_get_path('module', my_module') . '/data_sources/importchairs.csv', $columns);
		$this->destination = new MigrateDestinationNode('product_chair');
    $this->map = new MigrateSQLMap($this->machineName,
        array('chid' => array(
                'type' => 'int',
                'not null' => TRUE,
                'description' => t('chair-ID') // description never used
              )
             ),
        MigrateDestinationNode::getKeySchema()
    );
	 $this->addFieldMapping('title', 'name')
      ->defaultValue('')
      ->description(t('Product name'));
   $this->addFieldMapping('field_cat_number', 'cat_number')
      ->defaultValue('')
      ->description(t('Catologue number'));
    $this->addFieldMapping('field_cat_page', 'cat_page')
	      ->defaultValue('')
	      ->description(t('Catalogue number'));
    $this->addFieldMapping('body', 'full_desc');
    $this->addFieldMapping('field_designer', 'designer')
      ->defaultValue('');
    $this->addFieldMapping('field_width', 'width')
      ->defaultValue('');
		$this->addFieldMapping('field_depth', 'depth')
      ->defaultValue('');
		$this->addFieldMapping('field_height', 'height')
      ->defaultValue('');
		$this->addFieldMapping('field_seat_height', 'seat_height')
      ->defaultValue('');
    $this->addFieldMapping('field_price', 'price')
      ->defaultValue('');
		$this->addFieldMapping('field_chair_form', 'stool-bool')
      ->defaultValue(0);
		$this->addFieldMapping('uid')
		 ->defaultValue(13);
		// Other handlers
    $this->addFieldMapping('path')
      ->defaultValue(NULL);
    if (module_exists('pathauto')) {
      $this->addFieldMapping('pathauto')
        ->defaultValue(''); // Perform aliasing (set to 0 to prevent alias generation during migration)
    }
  }
}

That's all there is to it. Thoughts?

Comments

andjules’s picture

Follow-up: in my $columns, I named the last item "stool-bool". When I switched it to "stool_bool", the migration showed up in the UI. So, underscores not hyphens. Cool, and perhaps I should have thought of it, but a little error reporting would have been great.
I'm open to trying to contribute something in the error-reporting area, although admittedly, that may be a bit above my coding level.

As so many others tend to do at the end of their migrate issue, I'd like to say: this is one f*&^'ing cool module, and I am deeply grateful for it's existence.

andjules’s picture

and then, just as quickly and as mysteriously, the migration disappeared again :-(

mikeryan’s picture

Status: Active » Postponed (maintainer needs more info)

There's no reason hyphens in a field name should have an effect. Or, indeed, anything in the body of your constructor. All that matters is

abstract class my_module_BasicMigration extends Migration {
...
}
class my_module_ChairMigration extends my_module_BasicMigration {
...
}

This feels like a registry problem - the Drupal 7 class registry can be a little flaky sometimes, and lose track of classes in a way that makes it difficult for it to find them again (this is often triggered by moving a module to a different directory within your Drupal install). I would try the drush Registry Rebuild command and see if that clears things up.

If not, places to look:

  • The migrate_status table - see if Migrate has successfully registered your class, at least once.
  • The registry and registry_file tables - see if the core class registry knows where your class is defined.
  • The migrate_migrations() function in migrate.module - trace through to see why it's not finding your class, or recognizing it as a migration class.
andjules’s picture

Status: Postponed (maintainer needs more info) » Active

whoops, I guess that .install function registration is critical.

mikeryan’s picture

Status: Active » Postponed (maintainer needs more info)

I don't understand what you mean - a .install file is not necessary at all. The .info class registration via files[] is critical, but I'm assuming that your classes are defined in my_module.migrate.inc as suggested by your .info file.

andjules’s picture

If I don't use Migration::registerMigration (somewhere... I'm using a .install file), the migrations won't show up in the UI. Simply naming the .inc file (files[]) in my .info didn't seem to do it. However, the other time I used migration via CSV, I don't recall having to use Migration::registerMigration.

mikeryan’s picture

That is strange, I don't have an explanation. If you had derived from DynamicMigration instead of Migration, you would need to explicitly register your migrations, but you didn't do that.

Your naming convention is a little odd (the Drupal standard is CamelCase for class names), but I don't see why that would have an effect, unless the underscores (which are a single-character SQL wildcard) are throwing something off in the registry. I can't see anything in the Migrate code where that would have an effect.

mikeryan’s picture

From the Object-oriented code conventions:

Classes should not use underscores in class names unless absolutely necessary to derive names inherited class names dynamically. That is quite rare, especially as Drupal does not mandate a class-file naming match.

jrabeemer’s picture

The way I got around "No migrations" was to add this to my .info file.

files[] = "my_module.module"
files[] = "my_module.inc"

For some reason, the .module and subsequent hook_migrate_api() wasn't being called. I properly checked my class CamelCase() and drush cc all.

mikeryan’s picture

Status: Postponed (maintainer needs more info) » Closed (cannot reproduce)
LonitaD’s picture

I was having the same problem. I enabled my custom module but the classes were not appearing in the list on the migrate page. I am using the Commerce Migrate and Commerce Migrate Ubercart modules and the classes from those modules had no problems. I moved the class to the .module file instead of a .inc file to see if it made a difference. I tried testing if the site was reading the .module file by adding gibberish and I got a PHP error, so I knew the file was being read but the class was not registered. The solution for me was to add files[] = 'my_module.module' to the .info file. Seems strange but it works.

agileadam’s picture

I too had to include my .module file in my .inc file.

Luxian’s picture

I had the same issue. Declaring the ".module" file inside the ".info" didn't help. The classes were registered inside drupal "registry" and "registry_file" tables. The module hook was called, but no class was registered.

The fix for me was to run "drush mar" (or "drush migrate-auto-register").

holtzermann17’s picture

Version: 7.x-2.3 » 7.x-2.5

On Migrate 7.x-2.5, this is working for me (may or may not be the "right" way):

in .module:

function MYMODULE_migrate_api() {
  $api = array(
    'api' => 2,
  );
  return $api;
}

in .install:

function MYMODULE_enable() {
  Migration::registerMigration('...');
  Migration::registerMigration('...');
  Migration::registerMigration('...');
  ...
}