Take the 2-minute tour ×
Drupal Answers is a question and answer site for Drupal developers and administrators. It's 100% free, no registration required.

How can I save multiple values in a multi-value field collection using EntityMetadataWrapper ?

Here's some of my code

$field_collection = entity_create('field_collection_item', array('field_name' => 'MY_FIELD_COLLECTION'));
$field_collection->setHostEntity('commerce_line_item', $line_item);
$wrapper = entity_metadata_wrapper('field_collection_item', $field_collection);

for($delta=0; $delta<$max_delta; $delta++) {
  //MISSING something like $wrapper->setDelta($delta);
  $wrapper->field_example->set($new_value);  
  $wrapper->other_field_example->set($new_value); 
  $wrapper->save(); 

}

$field_collection->save();

I'm fighting with the field delta : I can't use $wrapper->field_example[$delta]->set($new_value) because the wrapper itself is the multi-value field, not its children fields.

So I need to find a way to perform something like

$wrapper[$delta]->field_example->set($new_value); 

But this returns "Fatal error: Cannot use object of type EntityDrupalWrapper as array".

Summary : where can I set the delta of the wrapper in the loop ?

share|improve this question
1  
You can't (not with setHostEntity(), anyway). That function just adds to the existing data, it doesn't offer a way to set the delta. The simplest way would be to reproduce the parts of that function you need and set the delta manually in your own function –  Clive Aug 26 at 14:51

1 Answer 1

up vote 5 down vote accepted

I've found this example in one of the bug reports on d.o, hopefully it will clear things up a bit:

// Load the entity and wrap it.
$entity = entity_load_single('my_entity', $entity_id);
$wrapper = entity_metadata_wrapper('my_entity', $entity);
// Create new field collection items.
$collections = array();
// This is a contrived example so assume $things contains some data that might be set on the collections.
foreach ($things as $thing) {
  $fc = entity_create('field_collection_item', array('field_name' => 'field_example_collections'));
  $fc->setHostEntity('my_entity', $entity, $entity->language, FALSE);
  // Skip saving the host entity since the order in which we are creating the items is not the order we want them saved.
  $fc->save(TRUE);
  $collections[] = $fc;
}
// Set the field collection items via the wrapper.
$wrapper->field_example_collections->set($collections);
// Save the entity.
$wrapper->save();

Just as @Clive commented, you need to first load the host entity that this field collection field is attached to (I'm assuming it's a commerce_line_item?), then loop through your data and create field collection entities. Then after you've done assigning values, collect them all in an array and set the array as the new value for the host entity's field collection field.

share|improve this answer
1  
That's a good way to do it - you can control the delta by setting the order of $things to something appropriate, it'll have the same effect. I think you probably want to change it to $fc->setHostEntity('my_entity', $entity, LANGUAGE_NONE, FALSE);, just to save duplicated effort to create the 'link'. It's minimal though –  Clive Aug 26 at 15:03
1  
Powerful code example! Just a point : I had to change $entity->save() to $wrapper->save(). Seems to be all right now. Tks again ! –  Kojo Aug 26 at 16:58
    
Last, I was wondering what @Clive meant by change to $fc->setHostEntity('my_entity', $entity, LANGUAGE_NONE, FALSE);, just to save duplicated effort to create the 'link'? –  Kojo Aug 26 at 17:18
2  
@Kojo It's minor, it just stops setHostEntity from adding the link to the field collection onto the host node explicitly, since you're adding it yourself with $wrapper->field_example_collections->set($collections);. Micro-optimising probably –  Clive Aug 26 at 17:28

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.