Field Collections Clone Data


Drupal 7
Batch Processes
Field Collection
01 Nov 2015


Use a Drush command to clone data from field collections to new field collections. This snippet loops through all field collection items of a given field collection and copies its data to new field collection items.


1. Drush Command with Batch Process will be autodiscovered by Drush after putting it in your module directory. MODULE_NAME_drush_command() implements hook_drush_command() and defines the Drush command as "drush update1". After putting this in your module directory and flushing the cache, navigate to your docroot using a terminal and run "drush update1". Because it could be a long process and could possibly time out, MODULE_NAME_drush_update_1() breaks the process up in to multiple batch operations.
 * Implements hook_drush_command().
function MODULE_NAME_drush_command() {

  $items['update1'] = array(
    'description' => t('Process update 1'),
    'aliases' => array('updr'),
    'callback' => 'MODULE_NAME_drush_update_1',
    'options' => array(
      'number' => t('The update number to run.'),

  return $items;

 * MODULE_NAME_drush_update_1_batch_process() actually processes the field collection
 * logic and migration. The process was timing out because it was running for too long, so it had to be
 * broken up by a batch process using this function.
function MODULE_NAME_drush_update_1() {

  $operations = array();
  $old_field_collections = array();
  // Sorting by "entity_id ASC, delta ASC" will ensure that field collection items are weighted the same on the new
  // field collection field as the original.
  $results = db_query("SELECT * FROM {field_data_field_image_hero} ORDER BY entity_id ASC, delta ASC");
  foreach ($results as $key => $result) {
    $old_field_collections[] = $result;

    // Every 20 records, create a new batch process and reset the old_field_collections array.
    if (($key != 0) && ($key % 20 === 0)) {
      $operations[] = array('MODULE_NAME_drush_update_1_batch_process', array($old_field_collections));
      $old_field_collections = array();

  // process remaining results
  $operations[] = array('MODULE_NAME_drush_update_1_batch_process', array($old_field_collections));
  $batch = array(
    'operations' => $operations,

  $batch = & batch_get();
  $batch['progressive'] = FALSE;

 * Migrate data from field collection field_image_hero to field_image_hero_landing on the same node,
 * and perform other minor updates to the nodes.
function MODULE_NAME_drush_update_1_batch_process($old_field_collections = array()) {

  foreach ($old_field_collections as $result) {

    $node = node_load($result->entity_id);

    // Load the original field collection.
    $field_collection_item = field_collection_item_load($result->field_image_hero_value);
    // Make the Entity API think this is a new entity by unsetting its item_id and revision_id.
    // Adjust the bundle (property field_name) to the new field collection field name.
    $field_collection_item->field_name = 'field_image_hero_landing';
    // Map node title and subtitle fields to the field collection item entity
    $field_collection_item->title_field['und'][0]['value'] = $node->title;
    $field_collection_item->field_subtitle['und'][0]['value'] = !empty($node->field_subtitle['und'][0]['value']) ? $node->field_subtitle['und'][0]['value'] : '';
    // Save new record. The object will be given a new item_id and revision_id that are used in the next step. These are the
    // properties of the new field_image_hero_landing field collection.

    // The field collection has been stored properly using the new field collection field, but it still needs to be related
    // to the base node. Add the new field_image_hero_landing field collection to the end of any existing field collections. 
    $node->field_image_hero_landing['und'][] = array('value' => $field_collection_item->item_id, 'revision_id' => $field_collection_item->revision_id);
    drush_log(t('Successfully migrated field collection item !item_id on node !nid.', array('!item_id' => $field_collection_item->item_id, '!nid' => $node->nid)), 'success');



Placeholder: I'll extend node comments with ajax and other functionality here.