Drupal - fast saving single field value
I'd definitely go for field_attach_update
.
The idea is simple. Just load the node and save it using field_attach_update.
Ex:
$node = node_load($nid);
$node->field_name[LANGUAGE_NONE][0]['value'] = 'New value';
field_attach_presave('node', $node);
field_attach_update('node', $node);
// Clear the static loading cache.
entity_get_controller('node')->resetCache(array($node->nid));
This will not changed any timestamp or any other hook that node_save usually invokes. Loading the node will also invoke some hooks so probably it's not that efficient.
If you have the nid and if the node structure is dead simple, you can do it like this as well:
$node = new stdClass();
$node->nid = $nid; // Enter the nid taken. Make sure it exists.
$node->type = 'article';
$node->field_name[LANGUAGE_NONE][0]['value'] = 'New value';
field_attach_presave('node', $node);
field_attach_update('node', $node);
// Clear the static loading cache.
entity_get_controller('node')->resetCache(array($node->nid));
Anyways, if you are trying to update anything other than than fields, this will no work (comment status, published status, etc). Also If you are using node_save, cache for the particular node will be cleared automatically for different methods we need to clear it with 'entity_get_controller'.
Update:
It appears that you should also call field_attach_presave()
to let other modules process the field input properly. File module, for example, uses it to set the file status to permanent using this hook. I have updated my 2 examples above.
I suggest field_attach_update
too, and not a direct SQL query, because sql doesn't update the node cache object, and in your next node_load
you wont load the updated field value, you will load the old value
field_attach_update
is much better than direct SQL query.
If you don't want to save field data without causing the standard events and actions to happen then you can use drupal_write_record.
Here is an example to insert Hello World into the body field for a node of type article with an id of 1.
$values = array(
'entity_type' => 'node',
'bundle' => 'article',
'entity_id' => 1,
'revision_id' => 1,
'language' => 'und',
'delta' => 0,
'body_value' => 'HELLO WORLD',
'body_summary' => '',
'body_format' => 'filtered_html',
);
drupal_write_record('field_data_body', $values);
drupal_write_record('field_revision_body', $values);
If your site is multlingual then you will want to use 'en' or the language of your content instead of 'und'.
If you are doing revisioning, you will have to be careful to insert the right revision id, otherwise you can simply insert the same value as the entity_id.
Note how this data is inserted into two tables field_data_* and field_revision_*. You should insert into both to make sure the site works as desired.
After running this you will then need to clear the caches for the fields to show up depending on how your caching is setup.