Migrate Field Collections
This page will describe the process of migrating field collections.
Field collections are separate entities, which are linked to host entities. That is why we have to create separate migration classes for every field collection field.
Your field collection migration should be run after the host entity migration. For example, if the collection is attached to nodes via a field named field_attached_data, and if the Article nodes are being imported by ArticleMigration, your collection migration class constructor will contain the code described below.
-
Specify dependencies
$this->dependencies = array('Article'); // 'Article' is the name given to the migration in your hook_migrate_api implementation.Because of this dependency, our field collection class
ArticleAlbumMigrationwill not be able to be imported untilArticleMigrationis fully imported. -
Specify destination
$this->destination = new MigrateDestinationFieldCollection( 'field_attached_data', array('host_entity_type' => 'node') );NOTE: if the host is a term, the correct host_entity_type would be 'taxonomy_term'.
-
Map host entity ID to source entity ID
$this->addFieldMapping('host_entity_id', 'source_article_id') ->sourceMigration('Article');
In general Field Collection migration works like any entity migration.
Working example
In this example we will set up a migration for an Article content type with an attached field collection field.
The Article content type has title and description fields only.
Let's assume we would like to add a list of album tracks to our Article. Let's create an Album field and set it type to Field Collection. In this example we will use a field with an unlimited number of values. Now we'll add fields to the Album field collection. Two fields will be enough: Title (Text) and Length (Integer).
Now we have fully configured the content type. Let's create the migration module. We will migrate data from a CSV source.
Module files
fc_migration
├── data
│ ├── albums.csv
│ └── articles.csv
├── fc_migration.info
├── fc_migration.migrate.inc
├── fc_migration.module
└── migrations
├── albums.inc
└── articles.inc
Contents of articles.csv
id,title,field_description
1,The Fame,The Fame is the debut studio album by Lady Gaga.
2,Born This Way,Born This Way is the second studio album by Lady Gaga.
Contents of albums.csv
id,article,field_title,field_length
1,1,Just Dance,240
2,1,LoveGame,215
3,2,Marry the Night,265
4,2,Born This Way,260
Let's define hook_migrate_api(). The best place to do it is in fc_migration.migrate.inc.
/**
* Implements hook_migrate_api().
*/
function fc_migration_migrate_api() {
$api = array(
'api' => 2,
'migrations' => array(
'Article' => array('class_name' => 'ArticleMigration'),
'ArticleAlbum' => array('class_name' => 'ArticleAlbumMigration'),
),
);
return $api;
}
Don't forget to include your classes in the module's info file:
files[] = migrations/articles.inc
files[] = migrations/albums.inc
This is the Article migration class
class ArticleMigration extends Migration {
public function __construct() {
parent::__construct();
$this->description = t('Articles migration from CSV source.');
$columns = array(
array('id', 'Article ID'),
array('title', 'Title'),
array('field_description', 'Description'),
);
$this->source = new MigrateSourceCSV(
drupal_get_path('module', 'fc_migration') . '/data/articles.csv',
$columns,
array('header_rows' => 1)
);
$this->destination = new MigrateDestinationNode('article');
$this->map = new MigrateSQLMap($this->machineName,
array(
'id' => array(
'type' => 'int',
'not null' => true,
),
),
MigrateDestinationNode::getKeySchema()
);
$this->addFieldMapping('uid', NULL)->defaultValue(1);
$this->addSimpleMappings(array(
'title',
'field_description',
));
}
}
This is the Albums migration class
class ArticleAlbumMigration extends Migration {
public function __construct() {
parent::__construct();
$this->description = t('Album field migration from CSV source.');
$this->dependencies = array('Article');
$columns = array(
array('id', 'Source ID'),
array('article', 'Article ID'),
array('field_title', 'Title'),
array('field_length', 'Length'),
);
$this->source = new MigrateSourceCSV(
drupal_get_path('module', 'fc_migration') . '/data/albums.csv',
$columns,
array('header_rows' => 1)
);
$this->destination = new MigrateDestinationFieldCollection(
'field_album',
array('host_entity_type' => 'node')
);
$this->map = new MigrateSQLMap($this->machineName,
array(
'id' => array(
'type' => 'int',
'not null' => true,
),
),
MigrateDestinationFieldCollection::getKeySchema()
);
$this->addFieldMapping('host_entity_id', 'article')->sourceMigration('Article');
$this->addSimpleMappings(array(
'field_title',
'field_length',
));
}
}
Now our module should be ready to perform migrations.
Note: There are plenty of suggestions and other examples in this issue.
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion