Feb 27 2008
Nik
Feb 27

Currently there are three options for creating error pages in the Drupal system, that I know of. I’m going to show here which I think is the best, for reasons of usability, performance and general webmaster sanity. At the foot of this article, there’s some free code too!

The options:

Drupal’s build in error page support

Drupal provides, out of the box, two fields in the Error Reporting configuration screen. These fields can be set to any internal Drupal path. Usually, they will be set to point the user to a page created specifically for the purpose.

The downside to this is that these will now be nodes in the system, and as such they will show up in popular content lists, site searches and the like. This is clearly not desirable.

Update: I have been made aware of an outstanding issue in Drupal core with error pages. This issue means that a user without “access content” permissions cannot access 403 error pages that are created as nodes. This is true in Drupal 5.x and even 6.1, and is another weak point for this mechanism.

Search404 module

Until very recently I was using search404 but I became less than pleased with the results. To start with, I thought I was aiding usability, but as it transpires… not really. The real killer for me is that search404 often gives me empty search result sets, because the path elements just don’t relate specifically enough to the content.

For instance, the node “/blog/my-drupal-article” will almost certainly contain all the words “my drupal article”, but may not contain the word “blog”, except in the path. This means the search doesn’t catch that article, so you get no results. Given that every 404 page the module generates incurs a DB query automatically, this query is effectively just trash, but cannot be disabled.

Customerror module

Customerror module skirts round the issues of having nodes as error pages. The module makes error handling pages available as custom paths inside Drupal. These aren’t nodes, so we have no issues there.

The configuration screen offers up two textarea fields which will contain the page content to be rendered on each of the 403 and 404 page errors. The key to making this more special than just a plain text or html page is the availability of PHP processing for these fields whilst not requiring nodes for the task.

Ok, so what I’m doing here is recommending customerror as the best choice for this task. That said, let’s throw down some code and make this more useful.

To start, visit the standard Drupal error reporting page at “/admin/settings/error-reporting”. Here, set the default error page fields to “customerror/403” and “customerror/404” respectively, if you’re going to override both these pages.

Now, on the Custom Error module’s config page at “/admin/settings/customerror”, enable both checkboxes that say “Allow PHP code to be executed for 40x”. Now let’s look at handling the 404 error. I’ve added the following code for this site, in the “Description for 404” textarea, and a suitably snappy title in the other field: “404 Not Found Error: No content found at the requested URL”.

<p>Sorry, no content was found at the requested path - it's possible that you've requested this page in error.</p>

<p>Use the search form below, or go to the <a href="http://www.kinetasystems.com/">home page.</a></p>

<?php
// check that the search module exists and the user has permission to hit the form
if (module_exists('search') && user_access('search content')) {
 
// cool! - customerror doesn't trash the page request and the full path is available
 
$path = $_REQUEST['destination'];
 
// bin anything that's not alphanumeric and replace with spaces
 
$keys = strtolower(preg_replace('/[^a-zA-Z0-9-]+/', ' ', $path));

  // retrieve the search form using the data we've pull from the request
  // note that we can override the label for the search terms field here too
 
print drupal_get_form('search_form', NULL, $keys, 'node', 'Search terms');
}
?>

In the 403 error fields, we adopt a similar technique. I’ve used “403 Forbidden Error: Access to this page is denied” for the title. Here we display different content depending on whether or not the user is logged in. If you’re running a site with lots of members, you can uncomment the user login line towards the bottom and the login form will be rendered on the 403 page!

<?php global $user; ?>
<?php if ($user->uid): ?> 
  <p>Sorry <?php print $user->name; ?>, you don't have permission to view the page you've just tried to access.</p>
  <p>If you feel that you have received this message in error, please
    <a href="http://www.kinetasystems.com/blog/creating-custom-error-pages-in-drupal/contact">contact us</a> with specific details so that we may review your access to this web site.</p>
  <p>Thanks</p>
<?php else: ?>
  <p>This page may be available to clients and registered users only. Please select from one of the other options available to you below.</p>
  <ul>
    <li><a href="http://www.kinetasystems.com/user/login?<?php print drupal_get_destination(); ?>">Login</a> to view this page</li>
    <li>Use the <a href="http://www.kinetasystems.com/blog/creating-custom-error-pages-in-drupal/search">search</a> facility</li>
    <li>Go to the <a href="http://www.kinetasystems.com/">home page</a></li>
    <li>Go to the <a href="http://www.kinetasystems.com/blog/creating-custom-error-pages-in-drupal/sitemap">site map</a></li>
  </ul>
<?php //print drupal_get_form('user_login'); ?>
<?php endif; ?>

Now we’ve got friendly, usable error pages that are helpful and don’t scare off visitors!

Updated 24th April 2008

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web