Profile picture for user admin
Daniel Sipos
20 Oct 2015

Have you ever needed to perform an action after a node has been inserted or updated? In this article we are going to see how we can trigger functionality after nodes have been inserted or updated. And no, it's probably not what you think.

By default, there is no hook that provides this in Drupal core. Sure, you have hook_node_insert(), hook_node_update() and hook_node_presave() but all of these are called within the scope of node_save(). This is important because, at this point, we cannot rely on the database for any data that may have been affected by the node save process. As the documentation for hook_node_insert() says:

when this hook is invoked, the changes have not yet been written to the database, because a database transaction is still in progress.

When you have to deal with something totally external to the node in question, this may not be a problem. Heck, you might not even need the database. But there are those one or two cases in which you do need data that has been affected by the process.

For example, when inserting a new node, various actions take place. One of them can be Pathauto doing some magic with the node title and saving a path alias for this node. So if you need to alter this final alias in the scope of hook_node_insert(), you cannot rely on something like path_load() to get the node alias data because it might have not yet been written. I've actually seen it return different things in different cases.

What you can do then is register a function with Drupal that will get called just about when Drupal is finished with the request. It's actually very simple. You just call drupal_register_shutdown_function() with the name of the function you want to be called. Additionally, you can pass as further arguments whatever it is in your context you want passed to it. It's kinda like subscribing a function to an event.

So now when the request is finishing, we know the node_save() database transaction has completed and we can rely on the data from the database. Using path_load() now will guarantee that the latest path for that node is being loaded.

Hope this helps.

Profile picture for user admin

Daniel Sipos

CEO @ Web Omelette

Danny founded WEBOMELETTE in 2012 as a passion project, mostly writing about Drupal problems he faced day to day, as well as about new technologies and things that he thought other developers would find useful. Now he now manages a team of developers and designers, delivering quality products that make businesses successful.

Contact us

Comments

@b_munslow 20 Oct 2015 13:29

Hi,

Hi,

Nice article.

In case it can help, the Hook Post Action module follows that exact method to expose several hooks that allow you to act after an entity has been inserted / updated / deleted.

https://www.drupal.org/project/hook_post_action

John 20 Oct 2015 13:23

There is already a module for

There is already a module for that :)
https://www.drupal.org/project/hook_post_action

Daniel Sipos 20 Oct 2015 19:18

In reply to by John (not verified)

:) Yes there is, but

:) Yes there is, but sometimes you may not need the entire thing just for one small use case. And knowing the power of drupal_register_shutdown_function() can be very helpful in other contexts as well :)

Elin 20 Oct 2015 18:18

There is a hook to alter the

There is a hook to alter the alias before it is saved: hook_pathauto_alias_alter().

David 02 Mar 2016 16:00

nice

Thanks Danny for informative article. I usually use module for this...However, your guide also is very helpful.

David

Mattew 31 Mar 2016 11:19

Debug inside a drupal_register_shutdown_function callback

Note that you will not be able to dsm() or var_dump() inside a drupal_register_shutdown_function callback function.
You may use your favorite IDE debugger (solution which I've not tested), or like me you can use an output file :

/**
 * Implements hook_node_update().
 */
function my_module_node_update($node) {
  if($node->type == 'my_type'){
    drupal_register_shutdown_function('_test_post_insert', $node);
  }
}

function _test_post_insert($node) {
  // debug the output
  file_put_contents('/temp/drupal-debug.txt', print_r($node, true));
}
Catweazel 12 Dec 2016 00:58

Great solution

Thank you Danny, you saved my day!
I need this solution for a client site with very complex forms using paragraphs and field_collection modules. To gain overall delivery performance i decided to prerender the 'body' part of the node content as drupal render items and store them serialized into a custom module table. Because some of the nodes are a sort of aggregation pages which show teasers of other nodes and therefore they need to be updated as well when an editor updates a teaser node.
The drupal_register_shutdown_function makes this implementation easy, clean and handy.
Thanx for that.

btw: referring to debugging opportunities inside the shutdown callback you can write as well to watchdog.

Add new comment