tags:

views:

420

answers:

2

Hi guys,

How can one hook exit in a custom module be called in every page request of a drupal website?

Here is the hook exit code in a custom module:

<?php
function cec_monitoring_exit() {
    if ((arg(0) == 'node') && is_numeric(arg(1)) && arg(2) == '') {
        // database inserts here
    }
}
?>

Is it because of the if condition or someting else? Because some of the custom modules are calling the hook 'cec_monitoring_exit()' but some other custom modules don't.

Thanks in advance.

Cheers, Mark

+1  A: 

Hooks are called whenever their condition is met. This is done with the use of module_invoke_all(). This means that hooks that are called on every page request, will be invoked in every page request. In your example above, your hook wont do anything in some cases, but it will still be called since Drupal wont know when it actually will do something.

This waste of resource will be limited when pages are cached, since you only will need to run the hooks when page cached page is created. Another example is whenever a node is loaded with node_load, this will result in a lot of hooks being fired, and is thus quite expensive. Thus you usually want to avoid using this whenever possible, when you want to access something on a lot of nodes like their title.

googletorp
@googletorp: Thanks for your answer.In the drupal 5 manual: "This hook is run at the end of each page request." So I think in every page request, the hook cec_monitoring_exit() will always be called without condition because the hook exit has no condition requirement? Am I correct?"In your example above, your hook wont do anything in some cases, but it will still be called since Drupal wont know when it actually will do something." - so it will still be called but why in some of the custom modules it is not being called?
marknt15
It's worth noting that unless you reset node_load, it holds a copy of each node in memory. Repeated loading of a node already in memory is not expensive. (So a node_load to access information about the current node page in hook_exit is fine.)
Grayside
+2  A: 

I'm not sure what you mean by it is not called in some of the custom modules either, so just speculating here that you might mean custom pages provided by other modules:

As Jeremy and Googletorp stated already, your if block

if ((arg(0) == 'node') && is_numeric(arg(1)) && arg(2) == '') {
    // database inserts here
}

will only evaluate to true if the user is requesting a full node page (e.g. 'node/42'). It will not match any other page like a term view (e.g. 'taxonomy/term/36') or the default frontpage ('node') or a view page provided by the views module (might/have/any/path), etc..

So your database inserts would only take place for node pages, and nothing else.

If you want to log every page request, you can just remove the if block and do your database insertions directly.


Edit after clarification in comments (cec_monitoring_exit() does not get invoked for some pages created by other modules):

I can only see two possible reasons for this.

The first reason would be an error occurring right after the page output, but before the invocation of your hook_exit() implementation (check your server logs for php errors on requests for the failing pages). If you take a look at 'index.php' (top level folder of your Drupal instance):

require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

$return = menu_execute_active_handler();

// Menu status constants are integers; page content is a string.
if (is_int($return)) {
  switch ($return) {
    case MENU_NOT_FOUND:
      drupal_not_found();
      break;
    case MENU_ACCESS_DENIED:
      drupal_access_denied();
      break;
    case MENU_SITE_OFFLINE:
      drupal_site_offline();
      break;
  }
}
elseif (isset($return)) {
  // Print any value (including an empty string) except NULL or undefined:
  print theme('page', $return);
}

drupal_page_footer();

you can see that the page output is generated by printing the result of theme('page', $return). The invocation of hook_exit() happens right after that in drupal_page_footer().

So you should check (preferably via debugger, but you could also use print statements) if drupal_page_footer() gets executed on the pages in question at all. If it gets called, the error might occur in a hook_exit() implementation of another module that gets called before yours, so you'd need to check those.

The second reason would be if one of the modules would circumvent the standard Drupal execution flow by calling theme('page', ...) itself and stopped the execution afterwards. In this case, drupal_page_footer() would not be called, because the execution would have stopped long before during the call to menu_execute_active_handler(). Note that no established Drupal Module would do this, so it is pretty unlikely.

Besides these options, I have no further idea on what could cause this.

Henrik Opel
Hi Henrick, thanks for the reply. Even if I replaced the whole code inside of the cec_monitoring_exit() hook with die('<hr />died here');the die function will not run in some custom modules.The one hook function I created must be called in every drupal page request right? But in some custom modules, the hook exit is not called. I'm wondering why.
marknt15
@marknt15: You need to explain what you mean by 'not run *in* some custom modules'! Why *in*? Do you place the same function in several different modules?
Henrik Opel
@henrick: I only have one hook function in one custom module and I did not have any other hook exit function. What I mean in 'not running in some other modules' is that the hook exit is not called in some custom modules when I access a drupal page.
marknt15
@henrick: Thanks for your help but I figured it out. The problem is not in drupal but in my PHP, Apache installation in Snow Leopard. I am using an individual install and it did not work. When I tried MAMP, the hook exit can now be called without doing anything in the code. Weird and I did not pinpoint exactly where is the problem in apache or php ini settings. Also, in individual install, the administer front page module is not showing up in a drupal fresh install.
marknt15

related questions