Hello,

I want to do calculations with the values of fields from a field collection. I have tried two methods that actually work because I use them in the node template temporarily, until I can get them working in a computed field. I've had no luck so far.

My field collection is called field_student, and the field I use to test this functionality is called field_bar

This is the first method, using entity_metadata_wrapper

global $node;
$meta_wrapper = entity_metadata_wrapper('node', $node);
$student_line = array();
foreach ($meta_wrapper->field_student as $line) {
    $student_line[] = $line->value()->field_bar;
    }
$t = count($meta_wrapper->field_student);
$totalbar = array();
for ($i = 0; $i < $t; ++$i) {
$totalbar[$i] = $student_line[$i]['und'][0]['value'];
}
$entity_field[0]['value'] = array_sum($totalbar);

This one throws the following error:

Error message
EntityMetadataWrapperException: Unknown data property field_student. in EntityStructureWrapper->getPropertyInfo() (line 339 of /var/www/ttms_db/sites/all/modules/contrib/entity/includes/entity.wrapper.inc).

The other method uses field_get_items

global $node;
        $field_collection_items = field_get_items('node', $node, 'field_student');
$field_collection_item_ids = array();
$i = 0;
foreach ($field_collection_items as $field_collection_item){
$field_collection_item_ids[$i] = $field_collection_item['value'];
$i++;
}
        $field_collection_item_fields = entity_load('field_collection_item', $field_collection_item_ids);
$bar_fields = array();
$i = 0;
foreach ($field_collection_item_fields as $field_collection_item_field){
$bar_fields[$i] = field_get_items('field_collection_item', $field_collection_item_field, 'field_bar');
$i++;
}
$bars= array();
$i = 0;
foreach ($bar_fields as $bar_field){
$bars[$i] = $bar_field[0]['value'];
$i++;
}
$entity_field[0]['value'] = array_sum($bars);

Error message here is:

Error message
EntityMalformedException: Missing bundle property on entity of type node. in entity_extract_ids() (line 7562 of /var/www/ttms_db/includes/common.inc).

Interestingly I only get these error messages when I'm not storing the computed field in the database. When I ask the field to store the value in the database, I don't get anything at all, no error, no field.

I'm sure someone who has a better understanding of php and Drupal API will know what to do with these error messages as they are quite descriptive, but unfortunately not to me. Someone suggested that the wrapper doesn't work because the fields are not loaded yet at that point in rendering the node, but I don't know. It works as intended when I put this code in node.tpl.php, but I would like to store these values in the database and display them in a view later.

I have read a lot of issue threads and requests, manuals and tutorials, to no avail. If someone can help me on this one I promise to write a wonderful how-to because I think it will help a lot of people.

Thanks!

BP

Comments

bump

Hi BP, your code helped my a lot. This is my code to copy field collection data in a computed field array. I hope I can help you back with it. I am now struckling with the $output. I prints the actual html entity instead of performing a line break.

<?php
function computed_field_field_risico_verzameld_compute(&$entity_field, $entity_type, $entity, $field, $instance, $langcode, $items) {
 
$field_collection_items = field_get_items($entity_type, $entity, 'field_risico'); // field_risico is node field
 
$field_collection_item_ids = array();
  foreach (
$field_collection_items as $field_collection_item) {
   
$field_collection_item_ids[] = $field_collection_item['value'];
  }
 
$field_collection_item_fields = entity_load('field_collection_item', $field_collection_item_ids);
 
$links = array();
  foreach (
$field_collection_item_fields as $field_collection_item_field) {
   
$tid = field_get_items('field_collection_item', $field_collection_item_field, 'field_risicoterm');  // field_risicoterm is fieldcollection field
   
$term = taxonomy_term_load($tid[0]['tid']);
   
$link = field_get_items('field_collection_item', $field_collection_item_field, 'field_link');  // field_link is fieldcollection field
   
$links[$term->name] = $link[0]['value'];
  }
 
$output = '';
  foreach (
$links as $term => $link) {
   
$output .= $term .' - '. $link .'<br />';
  }
 
$entity_field[0]['value'] = $output;
}
?>

Glad my code was of use to you! I'll look into yours and get back to this thread. Thank you for sharing it.

Hello Capono, I'm afraid I need some help understanding your code. Is the entire block of code wrapped into that computed_field_field_risico_verzameld_compute function? Is that an arbitrarily chosen function name or does it follow some naming convention? In any case I couldn't make it work for me, sadly.

Computed field gives you two choices: you can put your php code in the field directly or you can make your own function in a custom module, which I did. It is explained in the field description. So in my function name, risico_verzameld is the name of the computed field.

I see. So without seeing the code of your custom module I can't really make out what's happening there I guess. Would be interesting to look into that too.

I posted the complete compute function in comment#2. Create your own empty custom module (create an .info and .module file, put the function in the .module file, enable the module and go.