Voting starts in March for the Drupal Association Board election.
The Migration class is built on the fundamental assumption that there is a one-to-one correspondence between source rows coming in and destination objects going out.
If however your source data corresponds to more than one Drupal object or entity, there are several ways to deal with this depending on the complexity of the different destination objects.
Create dependent objects on the fly
If you have simple objects as dependencies of a more complex one, you can create these on the fly in your migrate class's prepareRow() or prepare() methods. This is particularly suitable if your dependent object's data is only one field in your source data.
The downside however is that these dependent objects are not cleaned up on rollback, and depending on how you make them, you may not be able to implement cleaning them up yourself (as once you've created the missing objects, you can't tell which ones were missing before).
A special case is taxonomy term reference fields, where the 'create_term' field option lets you create taxonomy terms for source data that doesn't match an existing term.
Even if your destination object requires more than one source field, it can be useful to take this approach. For example, here we create taxonomy terms on the fly by taking their term name from one source field and set a field value on them based on another source field:
// in prepareRow(): // Make a new term object to save. $names = taxonomy_vocabulary_get_names(); $edit = array( 'name' => trim($row->term), 'description' => '', 'parent' => array(0), // Note the vocab machine name must be converted to a vid. 'vid' => $names[$vocabulary_machine_name]->vid, ); $term = (object) $edit; // Set the field value from the row data. $term->field_myfield['und']['value'] = $row->term_myfield; taxonomy_term_save($term); // Put the new tid into the row's pseudofield. // This field needs to have been declared in the source's $fields parameter. // Remember also to set this field's 'source_type' to 'tid'. // The row now has the tid of a term that's just been created ready for the // taxonomy term reference field handler to work with. $row->term_tid = $term->tid;
Run multiple dependent migrations
For more complex cases, you can define more than one migration based on the same source data. The first migration creates the dependent objects, ready for the field(s) in the second migration to refer to. For example, you may want to create both users and Profile2 profile entities from the same CSV file.
There are two components that make this work.
First, the second migration is declared as being dependent on the first.
// Declare migration 'MyMigration_Step1' a dependency in migration 'MyMigration_Step2' to have them run in the right order, if needed: $this->dependencies = array('MyMigration_Step1');
Declare dependent field mapping
Second, the reference to the dependent object or entity needs to be obtained from the first migration's mapping, using that migration's map (this is the record of the relationship between Drupal IDs and your source's unique IDs). With users and profiles, this means that when the profile is created, its uid field is mapped from our source unique ID to the uid of the user created in the first migration.
This is declared by setting a sourceMigration on the field mapping, thus:
// Connecting the profile2 to the user. // We map from our source ID field to the uid, by way of Migrate's internal map. $this->addFieldMapping('uid', 'SOURCE_ID') ->sourceMigration('MyMigration_Step1') ->description(t('The assignment of profile2-items to the respective user'));
There is an example of this in action in the cookbook section of this documentation.