Drupal coder

How to define page callbacks that you don't want to render using page template in Drupal?

Defining custom pages in your Drupal module is easy using hook_menu and a callback function. Let's have a look at an example.

/**
 * Implementation of hook_menu().
 */
function my_module_menu() {
  $items['hello'] = array(
    'title' => 'Hello world',
    'page callback' => 'my_module_page',
    'access callback' => TRUE,
  );
}

function my_module_page() {
  return t('Hello world');
}

In this example, going to /hello will show you a page saying "hello world" rendered using your page template. So this page will display with your logo, blocks, footer, ...

In some cases you don't want this. Mostly in case you won't return HTML but something like XML, JSON, ... Let's have a look at two ways how this can be accomplished.

Method 1 : Printing your stuff and exit

The most popular option to implement this is by printing your output in your callback and then do an exit() call.

function my_module_page() {
  print t('Hello world');
  exit();
}

This works perfectly fine, but there's a drawback to this. A function that is called on each request will not be ran in this case: drupal_page_footer. This function takes care of page caching and running hook_exit.
Some modules depend on hook_exit to work properly. A popular one that comes to mind is the statistics module. This module logs each page request in hook_exit. But this hook is not called if you do an abrupt exit() call.

Method 2 : Printing your stuff and returning NULL

If you want that drupal_page_footer still gets called, just print out your stuff and return NULL instead of doing an exit() call.

function my_module_page() {
  print t('Hello world');
  return NULL;
}

This way drupal_page_footer get called, page caching still works and hook_exit is called for all modules that implement it.

It's up to you to decide which method is best in your case.

May 14, 2010

Comments

@Jonathan,

I realize it's a year old, but I ran into "Page Not Found" error on my Drupal 7 site. I had add

return $items;

in the functions_my_module () {...}

so the code looks like this:

/**
* Implementation of hook_menu().
*/
function my_module_menu() {
$items['hello'] = array(
'title' => 'Hello world',
'page callback' => 'my_module_page',
'access callback' => TRUE,
);
return $items;
}

function my_module_page() {
return t('Hello world');
}

It's one of those small annoying things that makes me hate computers. >:o

this is really helpful.

Very useful!

its very helpful.

Hello,

How come I get a 'page not found' error when I create a module and run this code?

Nice article, like Wim, I didn't know about it. Thanks!!! Merci!!!

The vast majority of the time you should return NULL. Reason is Drupal can now cache that, so the next request will hit the page cache for that request.

Ugh sorry, disregard my previous comment. The comments are in the opposite order than I expected.

Matt, as Davy pointed out, returning NULL is a way of indicating that you are intentionally returning nothing. If you don't put anything at all, nobody knows whether you just forgot to return something, or whether it was on purpose.

@Matt use exit if you want to skip the drupal_page_footer call. Returning null is the same as not doing a return but is a bit cleaner imho. It indicates that it was your intent not to return anything.

Why return anything or exit? Take a look at node_feed.

Nice one! I didn't know about this :) Thanks!