Assigning Node Field Values in Hook Insert and Update the Right Way

If you find yourself needing to manipulate node fields during hook_node_insert or hook_node_update, the best way is to use field_attach_update. Especially, if you need access the node id. Unlike hook_node_presave you can't just make assignments like so:

function example_node_presave($node) {
   $node->field_example_node_id[$node->language][0]['value'] = $node->nid;

Because if it's a new node, Drupal hasn't assigned the node id yet.


And you can't use the awesome entity_metadata_wrapper from the Entity API. Because Drupal will complain about duplicate nid entries in the database.

function example_node_insert($node) {
   $wrapper = entity_metadata_wrapper('node', $node);
   $wrapper->field_example_node_id = $node->nid;


So the right way to do this is with the field_attach_update.

function example_node_insert($node) {
   // Need to set the original property to avoid errors.
   $node->original = isset($node->original) ? $node->original : NULL; 
   // Assign field values.
   $node->field_example_field[$node->language][0]['value'] = 'some value';      
   field_attach_update('node', $node);

Now before you make the assignments, it's important to set $node->original or you may get this error "Undefined property: stdClass::$original in file_field_update()."


Note: If you want, you can also use field_attach_presave so other modules can act on the fields you altered.


That's it!