Drupal - How to run code on every page request - after modules are loaded?
I'd need something that runs after all modules are loaded - but before cached pages are served.
You cannot, as loading all the modules is the last phase of Drupal bootstrap, while cached pages are served in the second bootstrap phase.
See the code used by drupal_bootstrap().
switch ($current_phase) {
case DRUPAL_BOOTSTRAP_CONFIGURATION:
_drupal_bootstrap_configuration();
break;
case DRUPAL_BOOTSTRAP_PAGE_CACHE:
_drupal_bootstrap_page_cache();
break;
case DRUPAL_BOOTSTRAP_DATABASE:
_drupal_bootstrap_database();
break;
case DRUPAL_BOOTSTRAP_VARIABLES:
_drupal_bootstrap_variables();
break;
case DRUPAL_BOOTSTRAP_SESSION:
require_once DRUPAL_ROOT . '/' . variable_get('session_inc', 'includes/session.inc');
drupal_session_initialize();
break;
case DRUPAL_BOOTSTRAP_PAGE_HEADER:
_drupal_bootstrap_page_header();
break;
case DRUPAL_BOOTSTRAP_LANGUAGE:
drupal_language_initialize();
break;
case DRUPAL_BOOTSTRAP_FULL:
require_once DRUPAL_ROOT . '/includes/common.inc';
_drupal_bootstrap_full();
break;
}
If you look at _drupal_bootstrap_page_cache(), you will notice that hook_boot()
is eventually invoked before the page is served from the cached data, while hook_exit()
is eventually invoked after the page is served from the cached data. Those hooks are invoked if the value of the Drupal variable "page_cache_invoke_hooks" is TRUE
.
if (variable_get('page_cache_invoke_hooks', TRUE)) {
bootstrap_invoke_all('boot');
}
drupal_serve_page_from_cache($cache);
// If the skipping of the bootstrap hooks is not enforced, call
// hook_exit.
if (variable_get('page_cache_invoke_hooks', TRUE)) {
bootstrap_invoke_all('exit');
}
Notice that in Drupal 8, hook_boot()
has been removed and so does hook_exit()
. This means Drupal 8 will never invoke those hooks.
I think it's best to summarize the options in a new answer:
First off: There is no hook that's executed between hook_boot()
and hook_init()
. That means there is no hook that has a fully initialized drupal environment and is executed regardless of the page cache. -- thanks @kiamlaluno for clearing that up.
There are still two methods to get a similar effect:
- It's possible to selectively load include files or modules in
hook_boot()
using module_load_include() or drupal_load() respectively. This is especially useful if you only need some rather self-contained functionality which isn't spread over a lot of files. - The module dynamic_cache can be used to dynamically deactivate the cache on certain page loads by setting
$GLOBALS['conf']['cache'] = FALSE
inhook_boot()
and then do the heavy lifting inhook_init()
. - thanks to @David Meister
The two methods can also be combined to narrow down the number of requests where caching needs to be disabled: Use a minimal-bootstrap in hook_boot()
to determine exactly when caching needs to be disabled.
The dynamic_cache module seems rather hackish though. So I'll stick to method 1 for now.