1

Question: What are the properties that are essential to be defined in the entity passed to field_attach_update() for the function to update the appropriate fields (and not silently do nothing)?

This is not detailed in the field_attach_update API page and, in articles I can find written about it, it seems that what I have defined above (ID, bundle, field data to update) should be enough.


Context: I'm using field_attach_update(); to keep some fields on seperate entities in sync with each other, using code like this:

        // Load entity, get entity type data data...
        $entity = array_pop(entity_load($entity_type, array($entity_id)));
        $entity_info = entity_get_info($entity_type);
        $id_key = $entity_info['entity keys']['id'];
        $bundle_key = $endpoint_info['entity keys']['bundle'];

        // Do stuff with the entity, modify field_some_field
        do_stuff($entity);

        // Build stripped down object containing only essential data
        $lightweight_entity = new stdClass();
        $lightweight_entity->$id_key = $entity->$id_key;
        $lightweight_entity->$bundle_key = $entity->$bundle_key;
        $lightweight_entity->field_some_field = array(  
          'some_key' => 'some_data' 
          'another_key' => 'more_data' 
          );

        // Save it
        field_attach_update( $entity_type, $lightweight_entity );

This did work fine, but has recently (since updating to Drupal 7.14 I believe) been silently failing. No errors, nothing in logs - but no updates to the fields within Drupal and no changes to the field_data_field_some_field in the database. It seems like field_attach_update() isn't so much failing, as judging that it doesn't have any work to do. My theory is, that something is missing from the $lightweight_entity object, causing field_attach_update() to dismiss it as not a match or not a change.

(I'm piping in an entity object that is as simple as possible, partly because this sync function needs to run often and on many entity types, and partly because I have found that sending the whole original modified $entity object to field_attach_update() can result in PDO database fatal errors due to issues like this one, so simplicity is key. I'm using field_attach_update because it's syncing fields rather than updating the entity - new revisions data doesn't make sense in this specific context - from a user's perspective, the content hasn't been revised, and reverting the sync to become out of sync wouldn't make sense)

1

EDIT - Actually, it turns out that the core team have decided that passing in anything less than the whole entity to field_attach_update() is officially Wrong and not to be done. See http://drupal.org/node/1483736, if there is a file field (therefore, also media fields, image fields), and you update using field_attach_update() without including all the file field data, the file fields will be wiped.

So the correct answer in terms of the thinking of the core team is actually, all of them. As far as I know, it's only file fields that break like this, so you theoretically, in cases where passing in the whole entity object breaks, you could pass in entity id and bundle as below plus any previous file fields, but there's no guarentee nothing else would break.


Original answer - Actually after more testing and debugging, that first article seemed to have it spot on. The entity needs:

  • The entity id (as above)
  • The bundle (as above)
  • The field data, keyed with language (even if not applicable) and delta

(basically, so there's enough data to identify the entity and field instance)

...so my example above should have had:

$lightweight_entity->field_some_field[LANGUAGE_NONE][] = array(  
      'some_key' => 'some_data' 
      'another_key' => 'more_data' 
      );

And if the field name is dynamic, needs curly braces:

$lightweight_entity->{$field_name}[LANGUAGE_NONE][] = array(  
      'some_key' => 'some_data' 
      'another_key' => 'more_data' 
      );

Another relevant thing to note is, on a multi-item field, it replaces all items with what is entered here, regardless of what you put for the delta. E.g. if you have 5 items already, and try to add a sixth like this:

$lightweight_entity->{$field_name}[LANGUAGE_NONE][6] = ...

...it'll wipe the other 5. So, for multi-item fields which can already have data, you need to populate the mini-entity with all the items for that field before saving, for example:

if (!empty( $entity->{$field_name}[LANGUAGE_NONE])) {
  $lightweight_entity->{$field_name}[LANGUAGE_NONE] = $entity->{$field_name}[LANGUAGE_NONE];
}
$lightweight_entity->{$field_name}[LANGUAGE_NONE][] = ... 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.