When an entity (say, a node) has a field_collection, all you get when you load the node is the id of the field_collection entity.
$node->field_coll[$lang] = array(
array('value' => 12),
array('value' => 15),
);
And you need to separately load the field_collection 12 to access the values.
It would be handy to load the full entity within the loaded field value in field_collection_field_load() - a bit like file field does :
$node->field_coll[$lang] = array(
array(
'value' => 12,
'field_combo_1' => array(... the values ...),
'field_combo_2' => array(... the values ...)
),
array(
'value' => 15,
'field_combo_1' => array(... the values ...),
'field_combo_2' => array(... the values ...),
),
);
Gotcha with field cache - this means clearing the field cache of the host node when the field_collection is updated separately.
Then for extra handy programmatic manipulation, handle this format on save :
$node = node_load();
// Update 1st collection :
$node->field_coll['und'][0]['field_combo_1']['und'] = array(new values);
// Add a new collection on the fly :
$new_coll = new stdClass();
$new_coll->field_combo_1 = array(... the values ...);
$new_coll->field_combo_2 = array(... the values ...);
$node->field_coll['und'][] = (array) $new_coll;
node_save($node);
This means that the widgets have to produce that format on form submission, though.
Comment | File | Size | Author |
---|---|---|---|
#2 | entity_on_load-1227800-2.patch | 3.09 KB | yched |
#3 | entity_on_load-1227800-3.patch | 5.46 KB | yched |
Comments
Comment #1
yched CreditAttribution: yched commentedEdit, turns out that the save is already possible, and used by the widgets :
So it would be just a question of populating the 'entity' entry on field load ?
Comment #2
yched CreditAttribution: yched commentedA collection item saved individually triggers a save of its host entity, which takes care of clearing the cache. So it's just a matter of populating the 'entity' key on field load.
Additionally, performance++ for widgets and formatters (esp. on node listing pages) since this uses an entity_load_multiple() that spans over all the host entities listed on the page, rather than by host and by collection item.
I don't think we should run into infinite load loops, since a given collection item has one single host, and can therefore not be included inside itself, right ? (unlike a taxo term, or a noderef).
Patch attached.
Makes the following code possible :
Comment #3
yched CreditAttribution: yched commentedForget patch #2, forgot to commit last local changes and revert #1227244: Bug in formatter settings in Views before rolling.
Comment #4
rjbrown99 CreditAttribution: rjbrown99 commented+1 for me. I'll explain my use case.
I am adding a field collection to users, and I successfully added the collection (called field_role) using the embedded widget and defined two content taxonomy fields. This all works, and the fields show up on the user edit page. What I am noticing however is that when I programmatically do a user_load($uid); the returned object has a field definition that looks like your example from the top:
That's not particularly helpful to me, as I need to both create users programmatically (while populating this collection) as well as update existing users when values change. It seems like this patch would help with that.
Comment #5
rjbrown99 CreditAttribution: rjbrown99 commentedNice, the patch from #3 works great for my use case. In addition to what was showing in my post #4 above, under [value] I now see a populated [entity] object. I hope this patch makes it in as I'm going to start implementing stuff based on it :)
Comment #6
valderama CreditAttribution: valderama commentedWhen I use this patch, field_collection items can not be added anymore to the host entity by using the "add" link ( eg field-collection/field-bla/add/field_collection_item/853)
Can you imagine any reason for that? Or can you confirm this - or does it work for you?
Comment #7
rjbrown99 CreditAttribution: rjbrown99 commentedI have not tried to add new fields, I am using this with fields that were already created prior to applying the patch.
Comment #8
fagoI'm not sure we should always auto-load all the entities. Wouldn't it be more efficient and better for performance to only load them if needed? So e.g. a host entity using the hidden widget would not have to load + save all field-collections during node edit.
For easy access the entities one can already use the metadata wrappers, like this:
For adding a new collection simply do:
Comment #9
yched CreditAttribution: yched commentedDunno, might be argued, I guess.
I wasn't aware that the Entity API accessors allowed some transparent loading. The problem with loading them on demand (even if autoloaded wrapped in the entity API accessor) is that you load the deltas one by one (and entity by entity for listing pages), without benefiting from a single multiload.
Comment #10
fagoYep. You could do
too, which gives you all field collection items and makes use of multiple loading.
Comment #11
valderama CreditAttribution: valderama commentedcool - that hints helped :) thx, fago..
Comment #12
tim.plunkettI think this is related to #1259916-3: Load reference fields when building content.
Comment #13
patchshorts CreditAttribution: patchshorts commentedany news on this? I've ran all the patches on this and #1259916-3: Load reference fields when building content but I dont get my values loaded into the $node or $profile2 objects.
Comment #15
devtherock CreditAttribution: devtherock commentedHi,
Does anybody know how we can add multiple fields (with collection of fields) in my custom module while user adding a new node. I want to show pre fill fields to user.
Thanks.
Comment #16
edmund.kwok CreditAttribution: edmund.kwok commentedAny updates on this? I'm having difficulty saving values to fields in a field collection with multiple values.
field_addresses is the name of the field collection.
Any ideas?
Comment #17
kevinquillen CreditAttribution: kevinquillen commentedHow do you load a Field Collection when an entity is loaded? Is that in dev? I am importing data in and need to manipulate data programmatically to create/update entities.
Comment #18
tim.plunkettSee the documentation: http://drupal.org/node/1353926
Comment #19
kevinquillen CreditAttribution: kevinquillen commentedHow can you use EFQ to query and find data that already exists in a field collection, instead of overwrite it? I tried:
But I got SQL errors pertaining to field joins. I see the comment (http://drupal.org/node/1353926#comment-5342968) that shows how to load each one, but I want to load up a particular item matching certain values, unless there is another way to perform a field collection item update programmatically (without knowing its delta/id) other than this?
Fago's suggestion in #10 gives me all the data, but would it be faster to pick it out with the criteria I am looking for instead of looping and looking?
Comment #20
geek-merlinCrosslinking #1911158: Fieldcollection Wrappers should autocreate ("EntityMetadataWrapperException - Parent data structure is not set").