0

I'm writing a custom module for Drupal 6, and I need to execute some PHP no matter which page the user accesses.

I see that hook_init is not run on cached pages, so that's a no-go. hook_boot doesn't work, either, because it happens too early in the page request to let me use some functions I need.

So I was thinking about specifying a block using hook_block, but that hook just makes me pull my hair out:

function test_block($op='list', $delta=0, $edit=array()) {
  switch ($op) {
  case 'list':
    $block['test_block']['info'] = t('Test block');
    return $block;
  case 'view':
    $block = array();
    switch ($delta) {
    case 'test_block':
      $block_content = '<?php echo \'WTF?\'; ?>';
      $block['subject'] = NULL;
      $block['content'] = $block_content;
      break;
    }
    return $block;
  }
}

This renders as:

<div class="content">
    <!--?php echo 'WTF?'; ?-->
    <a id="context-block-test-test_block" class="context-block editable edit-global"></a>
</div>

Obviously, that's not what I'm looking for, either. Why does the PHP in that block not render correctly? Even if I end up using something other than a block to solve my problem, this issue really sparks my curiosity.

If I can't use hook_block, how do I get some PHP to run on every page? I need access to the $user global and to the drupal_goto() function.

3 Answers 3

4

What is wrong with your code is that the code that outputs the content of the block needs to be executed, such as:

$block['content'] = test_get_block_content();

This code makes sense if the code needs to output something in the page; if the code that needs to be executed doesn't need to output anything in the page, then hook_exit() is always executed, even on cached pages. The documentation for that hook reports the following text:

Only use this hook if your code must run even for cached page views. If you have code which must run once on all non cached pages, use hook_init() instead.

As for redirecting a user, you can look at what the Redirect module does to redirect a user. The purpose of the module is to redirect a user basing on the currently visited page, and on settings decided from an administrator user. The code that redirects the user is contained in this function, which is the implementation of hook_init():

/**
 * Implements hook_init().
 */
function redirect_init() {
  if (!redirect_can_redirect()) {
    return;
  }

  $current_path = current_path();
  $current_langcode = $GLOBALS['language']->language;
  $current_query = drupal_get_query_parameters();
  if ($redirect = redirect_load_by_source($current_path, $current_langcode, $current_query)) {
    redirect_redirect($redirect);
  }
  // …
}

The redirect_redirect() function is a wrapper for redirect_page_cache_clear().

function redirect_page_cache_clear($redirect = NULL) {
  if (!variable_get('redirect_page_cache', 0)) {
    return;
  }

  if (isset($redirect)) {
    $path = url($redirect->source, array('absolute' => TRUE));
    // Use a wildcard to catch paths with query strings.
    cache_clear_all($path, 'cache_page', TRUE);
  }
  else {
    // Clear the entire page cache.
    cache_clear_all('*', 'cache_page', TRUE);
  }
}

If you would implement a way to redirect a user through drupal_goto(), you should consider implementing hook_init() in a similar way.

1
  • Moving my block content into a function doesn't change anything at all, and hook_exit() happens too late to be of any use. I need to conditionally invoke drupal_goto(), but that doesn't appear to work in hook_exit().
    – arussell84
    Commented Aug 24, 2011 at 17:06
1

You can include files whose functions you need to access in hook_boot()

e.g.

require_once DRUPAL_ROOT . '/' . 'includes/path.inc';
require_once DRUPAL_ROOT . '/' . 'includes/locale.inc';

Obviously this means a bit more digging to determine precisely which files you need to include, but it can be done without too many headaches...

3
  • Why do you think the OP needs the "path.inc" file, or the "locale.inc" file?
    – avpaderno
    Commented Aug 24, 2011 at 16:46
  • Are there any drawbacks to this? Is there any reason not to use the drupal_load() function over require_once? Also, I'm having trouble seeing if I have access to the $user global in hook_boot(). Any ideas there?
    – arussell84
    Commented Aug 24, 2011 at 17:41
  • Alright, I've tried using require_once and drupal_load(), but neither work. drupal_goto() just doesn't seem to do anything regardless of what I try to include beforehand.
    – arussell84
    Commented Aug 24, 2011 at 19:54
0

I ended up using hook_init, since pages aren't cached for authenticated users. I only needed this PHP to run for authenticated users. I really wish I could have figured out what was going on with hook_block, though...

Your Answer

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

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