While the method described further down still works, a much better way of updating nodes is to use the entity metadata wrappers provided by the entity module. It’s much more clean and simple. Example:$node = node_load($nid); $node_wrapper = entity_metadata_wrapper('node', $node); $node_wrapper->field_foo_year->set(2015); $node_wrapper->save();
Please use entity metadata wrappers and skip the rest of this article unless you have a compelling reason not to.
Just like creating nodes, updating/editing a node programmatically in Drupal 7 is very simple. See the node creation page for guidance on how to set/update various field types (text, date, taxonomy, etc.); I won’t duplicate all that here. Instead I’ll show you additional things like deleting field data, deleting attachments and managing revisions.
I highly recommend using
print_r(node_load($nid)) (or drush:
drush php-eval 'print_r(node_load($nid))') to check nodes before and after modification; it’s a great way to learn about the data structures and see exactly what happens.
As always, don’t forget to make a backup of your database before you begin. If you have any questions, corrections or suggestions, please feel free to leave a comment.
Put the code below in e.g.
foo_update.php. Make sure it’s not accessible through the web (unless you don’t have shell access and must execute it through the browser and know what you are doing). In other words, put it outside your Drupal directory, and then just run
Also, just like when creating nodes, you have to make sure that the input is valid.title = "Let's set a new title for this node"; $node->body[$node->language]['value'] = "And a new body text, too."; node_save($node); echo "Node with nid " . $node->nid . " updated!\n"; ?>
If you use drush, you can skip the bootstrap part (lines 3-6) and, from your Drupal root directory, run
drush scr ../foo_update.php (assuming
foo_update.php is one directory above).
Deleting field contents
To remove field data, I suggest using
unset() like this:
So, to empty a field, just use
unset(). Often, however, you might want to do it conditionally. Say you have a term reference (taxonomy) field for tagging and want to remove a certain tag from a node. You can do it like this:
Deleting attached files
To delete an attached file from disk and delete its database record, use file_delete(): (Note: In Drupal 7,
file_delete() takes a file object as an argument rather than a path; Drupal 6’s
file_delete() is now
To remove a file that’s being used in the node, I’d do something like this:$filefoo = file_load($node->field_image[$node->language]['fid']); unset($node->field_image[$node->language]); file_delete($filefoo);
If this doesn’t seem to work, it’s most likely due to a problem with permissions. Check directory permissions and make sure the user running the script is able to remove uploaded files.
If you want to delete an attached file but keep the actual file on the server, you might think you could just unset the field:unset($node->field_image[$node->language]);
And you can. But the above will still keep the file’s database record - it’s removed from
file_usage but will still be in
file_managed. There doesn’t seem to be any existing API call we can use straight away. Taking a hint from the
file_delete() code, you can do this:
…or simply hack core. Here is another way to do it.
If you want to remove a file without touching the database (perhaps because the file is not in the database to begin with), you can use
I highly recommend using revisions when updating stuff programmatically. If something goes seriously wrong, it’s much easier to roll back to a previous revision than fiddling with database backups.
To make a new revision, all you need to do is set
$node->revision to 1, and optionally add a log message. Here’s the basic example again, this time with revisions enabled:
If you do
print_r(node_load($nid)); you’ll notice that the number of the latest revision is stored in
$node->vid. The first time you create a node,
$node->vid are the same. When you create a revision,
$node->nid stays the same but
$node->vid changes. Here’s how you load a specific revision of a node:
You can get a list of a node’s revisions with
node_revision_list($node). Note that this function takes a node object as its argument, so do something like this:
Pathauto URL aliases
If you use pathauto, it will overwrite custom aliases unless you explicitly disable it with the following:$node->path['pathauto'] = FALSE;
See How does Pathauto determine if the ‘Automatic URL alias’ checkbox should be checked or not? for more information.