Drupal has it's own system to handle "Page not found" errors. It uses a simple function, called drupal_not_found to set the correct headers, etc. That function calls theme_page to do its rendering.
The catch here is that it calls theme_page with the $show_blocks argument set to FALSE. This means blocks in the left and right columns won't be shown here.
// To conserve CPU and bandwidth, omit the blocks.
print theme('page', $return, FALSE);
In some cases, you might not want this behavior. You might have your navigation in one of these sidebars and you want to give your visitors some way out of this page. The navigation might get the person back on track.
How can we fix this? Very simple. Put the following code in your page preprocessing function.
function phptemplate_preprocess_page(&$variables) {
// show all regions if page not found
$page_not_found = strpos(drupal_get_headers(), 'HTTP/1.1 404 Not Found') !== FALSE;
if (!$variables['show_blocks'] && $page_not_found) {
global $theme;
// Populate all block regions.
$regions = system_region_list($theme);
// Load all region content assigned via blocks.
foreach (array_keys($regions) as $region) {
// Prevent left and right regions from rendering blocks when 'show_blocks' == FALSE.
if ($region == 'left' || $region == 'right') {
$blocks = theme('blocks', $region);
}
// Assign region to a region variable.
isset($variables[$region]) ? $variables[$region] .= $blocks : $variables[$region] = $blocks;
}
}
}
This will only render the left and right blocks, the other ones are already rendered by Drupal core.
It seems like a lot of people forget about this. Maybe because they don't know how to set up a cron. But if you use the watchdog, and you want to periodically discard your old log entries (admin/settings/error-reporting), you should also set up your cron.
If you don't know how to do this, read the Drupal cron documentation.
If you're using Drupal 6, you might consider using Acquia's Drupal distribution which enables cron by default from their servers.
And if you don't have access to set the cron on your server, Poormanscron is a great alternative.
When a user requests a page he's not allowed to see, he gets an 'Access denied' page with the message 'You are not authorized to access this page. '.
Sometimes the user has access to the page but he hasn't logged in yet. So to make the user's life easier, you provide him with a login form on the 'access denied' page so he can login immediately and gets redirected to the page he requested originally.
How do you do this?
Start by creating a new Page (node of type Page). Set the input format for the body to 'PHP code'. Start typing the message you want to give to the user, something like 'This page is restricted to logged in users. Please provide your credentials below.'.
You then display the login form my typing the following code below your message (or anywhere you want to put the login form):
<?php
print drupal_get_form('user_login');
?>
If you also want the 'Create new account' and 'Request new password' links under your form you can use the login block by typing the following code instead of the previous:
<?php
print drupal_get_form('user_login_block');
?>
Voila, your page is done. But you won't be able to see it since you are logged in right now. So to test your page log out and go to your page. If you don't know the drupal path of your page, go to Administer > Content Management > Content to find it.
To finish setting up your page, you have to tell Drupal to use your new page as the 'Access denied' page. You can do this by going to Administer > Site configuration > Error reporting and providing the drupal path of your new page for the 403 page.
By default Drupal discards your log entries older then one week. This is done to keep your database small and sharp by throwing out irrelevant log messages.
But sometimes you just want your log messages to be discarded at all. You can override Drupal's default behaviour by altering a setting in the administration section.
Go to Administer > Site configuration > Error reporting (admin/settings/error-reporting).
You will find a setting there saying 'Discard log entries older than'. Well, that was what we were looking for :)
By default, Drupal error logging happens to the log database (the watchdog table) and the screen. This is something I had overlooked for quite a while untill I stumbeled upon it while setting the error pages.