Hi

I want to add a "field collection" dynamically. But I'm not familiar with Field API or Entity API. New Entity API in Drupal is very poorly documented. For example "entity_create" is not documented at all.

I would appreciate if someone could show me the right path to add a field collection by script.

Comments

Mamouri’s picture

Here is my code, until now:

	$node = node_load(1);
	$field_collection_item = entity_create('field_collection_item', array('field_name' => 'field_book_text'));
	$field_collection_item->setHostEntity('node', $node);
	
	// Adding fields to field_collection

	$field_collection_item.save();

"Field Collection" module use function "entity_form_submit_build_entity" which I cannot use because there is no form in my case.

I would appreciate if you can tell me how can I add fields?

Mamouri’s picture

Here is what I achieved and it seems it works:

	$node = node_load(1);
	$field_collection_item = entity_create('field_collection_item', array('field_name' => 'field_book_text'));
	$field_collection_item->setHostEntity('node', $node);

	$field_collection_item->field_text = array(
		'und' => array(
			'0' => array(
				'value' => 'Text',
				'format' => 'filtered_html',
			)
		)
	);

	$field_collection_item->field_text_type = array(
		'und' => array(
			'0' => array(
				'value' => '1'
			)
		)
	);

	$field_collection_item->save();

I would appreciate if you can confirm this is totally right or if it could improve, improve it.

tcalin’s picture

I use the same sequence and it worked for me until I upgraded recently to Entity API 7.x-1.0-beta9 when everything broke.
Now wither saves only some of the field-collection fields or it simply blocks until exceeds the maximum execution time.
I am still invetigating the issue.

rbruhn’s picture

Not sure if this will help but I updated #1106182: Creating field collection programatically with an example of what I'm doing programmatically. It's for the 7.x-1.x-dev branch though.

Edit: Using Entity API 7.x-1.0-beta9 too

tcalin’s picture

Have you tried this in the configuration Drupal 7.2 Entity API beta9?
I get strange results like field collection saved partially or not at all.

tcalin’s picture

In some situations I get this error from apache. There is a recursion that seems to go forever

Maximum execution time of 120 seconds exceeded in /var/www/kalimera/includes/bootstrap.inc on line 1821

In other situations the field-collection is saved but with some fields missing.

rbruhn’s picture

I'm using Drupal 7.2 and Entity API 7.x-1.0-beta9
Had to edit my post on the other issue. I forgot to replace $key with $field['instance']['field_name'] when checking for the field instance.
But other than that, it works for me.

tcalin’s picture

I use your sequence in two situations:
- in the first one the field collection is saved except two fields. It is strange that the form works ok.
- in the second one the field collection can not be saved no mather I try from code or using the form. It fails with the message from #6

Both pieces of code used to work before Entity API beta 9.
This is certainly a bug but It is not very clear for me where to report it.

rbruhn’s picture

Perhaps uninstall Entity API and reinstall it? Maybe something got corrupted or is cached.

Edit: I'm about to run a migration script to move 1000 records. Will let you know how it goes.

tcalin’s picture

I have tried this but without result.

We have this announce on the project's page.

Important note:
Entity API version 1.0-beta9 comes with some API changes for modules using it to implement exportable entities, such as Rules, Profile2, Search API, Organic groups, WSClient and Message.
When updating, you have to update all of those modules to their new versions which are compatible with beta9 at once. When doing so, update the code of all modules and then run update.php!

Seems like a good point to start the investigation.

rbruhn’s picture

Ran my migration script and everything went in correctly. The code below is the exact code I used during migration. Understand.... my custom node is called "bir_collection," and that my "field collection" is also called bir_collection. I then attached bir_collection_node to the field collection.

$result is a DB object from the legacy database.
$nids are the new node ids for the old database objects that have been migrated. So, my collections have multiple nodes in them. If you wonder why I used field collection instead of just a normal field for the node reference, it's because I'm planning on adding other fields later.

Anyway... it worked. Not sure why you are having problems.

// Create new collection node
$node = new stdClass();
$node->type = 'bir_collection';
node_object_prepare($node);
$node->title = $result->name;
$node->language = LANGUAGE_NONE;
$node->created = $result->created;
$node->changed = $result->changed;
$node->status = $result->public;
$node->uid = $submitter_uid;
$node->contributor[LANGUAGE_NONE][0]['uid'] = $contributor_uid;

map_legacy_field_data($node, $result);

echo "Saving node for Collection object $result->boid\n";
db_set_active();
node_save($node);

// Loop through nids and save to field collection
echo "Saving CollectionObjects for Collection node $node->nid\n";
foreach ($nids as $key => $nid) {
  $field_collection_item = entity_create('field_collection_item', array('field_name' => 'bir_collection'));
  $field_collection_item->setHostEntity('node', $node);
  $field_collection_item->bir_collection_node[LANGUAGE_NONE][]['nid'] = $nid;
  $field_collection_item->save();
}
tcalin’s picture

I have tried using your sequence. I also used the one from below which is a little bit different.
No way I can get crmtsk_tsk_unit_price and crmtsk_tsk_total_price saved.

<?php
  foreach ($query->execute() as $row) {
    $task_tsk = array();
    $task_tsk['field_name'] = 'crmtsk_tasks';
    $task_tsk['is_new'] = 1;
    $role = '';
    $unit_price = 0.0;
    if ($form_state['values']['collab'] == $row->responsible) {
      $role = 'rsp';
      $unit_price = $row->rspfee;
    }
    else {
      $role = 'rvs';
      $unit_price = $row->rvsfee;
    }
    $task_tsk['crmtsk_tsk_id']['und'][0]['value'] = $row->crmprj_services_value;
    $task_tsk['crmtsk_srv_id']['und'][0]['value'] = $row->service;
    $task_tsk['crmtsk_tsk_role']['und'][0]['value'] = $role;
    $task_tsk['crmtsk_tsk_quantity']['und'][0]['value'] = $row->quantity;
    $task_tsk['crmtsk_tsk_unit_price']['und'][0]['value'] = (float) $unit_price;
    $task_tsk['crmtsk_tsk_total_price']['und'][0]['value'] =  (float) _service_get_quantity($row->service, $row->quantity) * $unit_price;
    $task_tsk['crmtsk_tsk_desc']['und'][0]['value'] = isset($row->description) ? $row->description : '-';

    $tt = new FieldCollectionItemEntity($task_tsk);
    $tt->setHostEntity('node', $task);
    $tt->save();
  } 
?>
lucor’s picture

#12 works for me. I'm using Entity API 7.x-1.0-beta9 and Field Collection 7.x-1.x-dev branch.

tcalin’s picture

Finally it worked for me too.
But I still have an entity which does not work no matter I try from the script or using the form.

It seems that someone here http://drupal.org/node/1203018 is having the same problem as me.

phreestilr’s picture

Thanks, rbruhn!

tim.plunkett’s picture

Priority: Critical » Normal
Status: Active » Fixed

So, this is fixed?

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

cornel.eftimie’s picture

this is the best solution for working with field collection, it works great!
http://rajanmayekar.com/blog/programmatically-creating-deleting-modifying-field-collection-item-node

hvasconcelos’s picture

Thanks for sharing, that helped!