7

Of the various hooks called during the entity save process, which is the very last to be called?

Is there a way to trigger an event after the entity has been created, after all fields have been saved, after caches updated, etc? So that, when a user saves the update form, this action is the very last thing to happen before the redirect page is loaded?

If it's not strictly part of the save process, that's fine. What matters is: it's called after everything to do with an entity being saved. If there's a way of hooking some form function and reliably identifying from the data in there that a save process has been completed, or defining some callback, that's fine by me.

(context: I've got a problem where field caches are being created that caused newly created nodes, and other fieldable entity types, to load as if they are blank and as if they have no field data - but all attempts so far using cache_get and cache_clear_all don't find the cache - it's being created late in the process. So I'm looking for the latest possible hook which will definitely get it)

(Relevant info: hook_entity_postsave doesn't exist, and is one of those core issues that got stuck months and months ago)

1

3 Answers 3

3

The various wrapper functions (node_save(), user_save(), etc.) are responsible for resetting the entity cache after the save method has been invoked on an entity controller.

If you take the user_save() function as an example, this cache reset happens after the function invokes the various entity hooks (same goes for node_load())

That in mind, I think the question then becomes "What is the last hook to be called during an entity save"?...and the answer is hook_entity_update() / hook_entity_insert(). But, they are called before the cache is reset (for obvious reasons).

The entity_save() method just invokes the save handler for that particular entity type, and doesn't invoke any hooks of its own, so really your only options are:

  • Roll your own entity controller for the various entities you need to intercept, changing the save() method to invoke a hook after the cache has been cleared.
  • Hack/patch the existing entity controllers with the same code.

Neither are particularly attractive options but unless there's a solution available at a higher level that I'm not seeing, I don't think you've got much choice.

6
  • Argh! What about during the redirection process? node_save() etc must call a function to trigger the page redirection after completing everything and saving caches - is there any way of using this? Or, assuming as with nodes that it redirects to the newly saved entity, any way of triggering a cache clear the first time an entity is viewed? Aug 8, 2012 at 11:22
  • 2
    It's the form handler that performs the redirect, not the _save() function, so I guess you could hook into the form and add a submit handler to the end of the array of submit functions (so it gets run last). In your submit handler the _save() function will have been run, and presumably the caches cleared, so you can intercept it at the right time. But again I don't think there's a generic solution that will work across all entity types, and it will only work if the entity is created via a form, and not programatically.
    – Clive
    Aug 8, 2012 at 11:27
  • Forcing a cache clear when the entity is first viewed would require keeping a variable somewhere (perhaps a custom table) for each entity that determines whether or not that cache flush has been run, and performs it if not. So you'll need to store entity_type, bundle, and entity_id along with that boolean value (similar to the field_data_* tables). hook_entity_view() would be the place for that logic.
    – Clive
    Aug 8, 2012 at 11:30
  • The option in your first comment sounds like it could be the way to go. One more question though if you don't mind: it does sound like my problem cache is the one created at the end of the entity_save process, which makes me wonder how it can be that the field cache created doesn't match the entity object that has just been saved. But I can't find the code that calls the cache creation in entity_save or node_save to begin debugging - only code that clears the old cache. Would it be in the entity class definition? Not sure where to look for that. Thanks Aug 8, 2012 at 13:31
  • 1
    The caching decisions happen at a slightly lower level than node_save()...in the DrupalDefaultEntityController class (which NodeController extends). In a nutshell it's the DrupalDefaultEntityController::load() function which queries the cache, and forces a live load of the data if a suitable cache cannot be found. That might be the best place to start back-tracking from
    – Clive
    Aug 8, 2012 at 13:47
2

I had a similar problem where I wanted to execute a view after a node was saved. The node appeared in the view but had old data on the fields despite just having been saved. Subsequent calls to the view had the latest field values.

I called the following at the start of my hook_node_update which appears to solve the problem (for me).

/**
 * Implements hook_node_update().
 */
function mymodule_node_update($node) {
  // Clear internal properties.                                           
  unset($node->is_new);                                                   
  unset($node->original);                                                 
  // Clear the static loading cache.                                      
  entity_get_controller('node')->resetCache(array($node->nid));  

  // Rest of my code e.g. execute a view.
}

This reset cache command is what is run by the node_save function after invoking all the hook_node_update's.

1
2

Yes, there is an addon module which provides hook to invoke after an entity is saved. It's called Hook Post Action. This was already answered on stackoverflow.com.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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