Search code examples
drupaldrupal-7

How to add / update a field collection without updating parent node/entity drupal 7


I needed to to add / update field collections to node entities without updating the node entities. I tried two ways listed in https://www.drupal.org/node/1842304 and http://alexrayu.com/blog/saveupdate-field-collection-without-nodesave but none of them seems to be working exactly the way I want.

I tried as follows:

$node = node_load($nid);
$field_collection_item = entity_create('field_collection_item', array('field_name' => 'field_college_rating_data'));
$field_collection_item->setHostEntity('node', $node);
$field_collection_item->field_text1['und'][0]['tid'] = $form_state['input']['field_text1']['und'];
$field_collection_item->field_text2['und'][0]['value'] = $form_state['input']['field_text2']['und'];
$field_collection_item->save();

It added a field collection but it updates the node.

I also tried to alter the field collection form submit and used custom submit handler as follows:

function own_custom_field_collection_submit($form,$form_state) {
  $field_collection_item = field_collection_item_form_submit_build_field_collection($form, $form_state);
  $field_collection_item->save(TRUE);
  drupal_set_message(t('The changes have been saved.'));
  $form_state['redirect'] = $field_collection_item->path();
}

I have copied this code from core field collection module to change the default argument to "TRUE" in the save function. It added the field collection but didn't associated with the parent node.

I need to save the field collection separately since my node entity form is very large with 50 to 60 fields and field collections and I don't want to update it as many times as I add / update any field collections to the node.

Any help will be much appreciated. Thanks


Solution

  • You have to pragmatically relate your field collection to the host entity by the following code.

    $field_collection_item = field_collection_item_form_submit_build_field_collection($form, $form_state);
    $field_collection_item->save(TRUE);
    $host_entity = $field_collection_item->hostEntity();
    $lang = 'und';
    if (isset($host_entity->nid) && isset($host_entity->vid) && isset($lang) && isset($field_collection_item->item_id) && isset($field_collection_item->revision_id)) {
      $query = db_select('field_data_field_text1', 'fd');
      $query->addExpression('max(fd.delta)', 'total_row');
      $query->condition('fd.entity_id', $host_entity->nid);
      $max_delta = $query->execute()->fetchField();
      if (isset($max_delta)) {
        $max_delta = $max_delta + 1;
      } else {
        $max_delta = 0;
      }
      db_insert('field_data_{field_collection}')->fields(array(
        'entity_type' => 'node',
        'bundle' => '{node_type}',
        'entity_id' => $host_entity->nid,
        'revision_id' => $host_entity->vid,
        'language' => $lang,
        'delta' => $max_delta,
        'field_text' => $field_collection_item->item_id,
        'field_text_revision_id' => $field_collection_item->revision_id
      ))
      ->execute();
    }
    

    Replace your content type and field type in { } and then you just have your field collection relate to your host entity. Thanks