Programmatically Create Field Collections in Drupal

I've been working on a pretty big site restructure this week and as part of the restructure I needed to migrate data from some custom database tables into Field Collections to offer a bit more flexibility. Most of the code documented was available on drupal.org but there was definitely a lot of different ways mentioned and no clean cut function for you to reuse. If you're just looking for a cut a paste, here's the code. I will explain it further below but it's pretty well commented anyway.

<?php 
/**
 * Creates a field collection.
 *
 * @param $parent
 * @param $type
 * @param $collection_name
 * @param $values
 * @return object
 */
function _module_name_add_field_collection($parent, $type, $collection_name, $values) {

  // Create entity using the entity name and set the parent.
  $field_collection_item = entity_create('field_collection_item', array('field_name' => $collection_name));
  $field_collection_item->setHostEntity($type, $parent);

  // EMW makes it easier for us to work with the field_collection
  $field_collection_item_w = entity_metadata_wrapper('field_collection_item', $field_collection_item);

  // Add the fields to the entity.
  foreach($values as $key => $value) {
    $field_collection_item_w->{$key}->set($value);
  }

  // Save the entity.
  $field_collection_item_w->save();

  return $field_collection_item;
}
?>

Usage

If you need some further help here is a breakdown of each parameter. $parent - This is the parent of the field collection. This will usually be a node or taxonomy object but it can also be a field collection. $type - This is the type of the parent. It could have probably been pulled from the parent object. This should be node, taxonomy_term or field_collection_item. $collection_name - This is the name of the field collection field. If you have a node with a field called "field_pricing" which is a field collection then this parameter should be field_pricing" $values - Key values pairs of data that should be added to the field collection. The keys will be field names that are within the field collection.

Comments

Permalink

Thank you this helped me out a lot.

A helpful tip to anyone thinking of creating field collections on the fly to add to a node during a migration (using the migrate module):

Firstly, use the migrate module's prepare() method because what you need is the parent node to have already been created, and after it creates the parent node, it passes it as an object to the prepare() method automatically via the $node argument and you can use this in the setHostEntity() method - $field_collection_item->setHostEntity($this->destination->getEntityType(), $node);

Permalink

really Helpful, its worked straight way , i was trying below code , but not sure where I was mistake as getting error"Integrity constraint violation: 1048 Column 'field_item_target_id' cannot be null"
$nid = 67;
$nod= node_load($nid);
// Create a new field collection
/$field_collection_item = entity_create('field_collection_item', array('field_name' => 'field_order_items'));
$field_collection_item->setHostEntity('node', $nod);

// Load items into field collection
// $field_collection_item->field_item[$nod->language][0]['value'] = "67";
$field_collection_item->field_quantity[$nod->language][0]['value'] = 11;
$field_collection_item->field_type[$nod->language][0]['value'] = "small";

// Save field collection item
$field_collection_item->save();

Permalink

Hi
I dont understand how to 'register' the fc : _module_name_add_field_collection is not a hook; where should we put the code ? How is it called ? Isn't there any hook_field_collection_info, like for fields ?

Add new comment

The content of this field is kept private and will not be shown publicly.

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.