Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
I needed a way to load all the data of a node with multiple nested FC fields. Couldn't find it done before so I modified the code at http://drupal.org/node/1233256#comment-5167316 to not clone but to fully populate (load) an entity with FC fields. It searches for FC reference fields and replaces them with loaded FC entities. Posted here if anyone else finds this useful or perhaps be included in the module?
Usage:
load_all_fc_fields('node', $node);
$node now has the actual data and not just FC references. All FC child fields
<?php
/**
* Recursively replaces all references to field collection entities with the actual field collection entity
*
* @param $entity_type
* @param $entity
* @param string $language
*/
function load_all_fc_fields($entity_type, &$entity, $language = LANGUAGE_NONE){
$field_info_instances = field_info_instances();
// Search for all fields of $entity that are of the type field_collection_item
// and operate on them
foreach($field_info_instances['field_collection_item'] as $field_name => $field_info){
if(isset($entity->{$field_name})){
load_fc_field($entity_type, $entity, $field_name, $language = LANGUAGE_NONE);
}
}
}
/**
* Replaces references to field collection entities with the actual field collection entity
*
* Recursive for all child fields of $fc_field that are also field collections
*
* @param $entity_type Type of $entity
* @param $entity By reference, the entity being operated on
* @param $fc_field Name of field to replace references in
* @param string $language
*/
function load_fc_field($entity_type, &$entity, $fc_field, $language = LANGUAGE_NONE){
$entity_wrapper = entity_metadata_wrapper($entity_type, $entity);
$fc_items = $entity_wrapper->{$fc_field}->value();
if (!is_array($fc_items)) {
$fc_items = array($fc_items);
}
$field_info_instances = field_info_instances();
$field_names = element_children($field_info_instances['field_collection_item'][$fc_field]);
// This is where the references to field collection ids is changed to the
// actual loaded entity
foreach($entity->{$fc_field}[$language] as $item_key => &$item){
$item = $fc_items[$item_key];
}
foreach ($fc_items as $fc_item) {
$fc_item_wrapper = entity_metadata_wrapper('field_collection_item', $fc_item);
// Now check if any of the fields in the newly cloned fc item is a field collection
// and recursively call this function to properly populate.
foreach ($field_names as $field_name) {
if (!empty($fc_item->{$field_name})){
$field_info = field_info_field($field_name);
if ($field_info['type'] == 'field_collection'){
load_fc_field('field_collection_item',$fc_item, $field_name,$language);
}
}
}
}
}
?>
Comments
Comment #1
jiong_ye CreditAttribution: jiong_ye commentedthank you. it works well. but i did find that if i use node_load to load a node before running it through this function it would give me an error after the first run. i think it was due to the fact that node_load caches the node, so on the second time you run node_load, you dont need to run your function again because it's already populated.
i added a check to your function