I hate modules, especially core modules. I prefer code to be tightly integrated. I want it to work together. Is that too much to ask? In Drupal, most functionality has been stuffed in modules. There’s a Locale module, a Content Translation module and a Path module. What’s missing is a Working Together module.
For me, clean, meaningful URLs are a number one, two and three requirement for any website that I do. Drupal considers /node/54673 to be a cool URL. I don’t. So, as a kind of afterthought, Drupal comes with the Path module. This module allows you to set URL aliases per node.
The problem is that there’s no concept of a canonical URL. The URL alias works, but so does the node/3242 URL. Neither redirects to the other. In many cases this is not much of a problem (because regular visitors will not notice this) but for our current project it is.
We have a lot of blocks with URL dependent visibility settings. For example, for a section about investing we have a menu that is displayed on all URLs starting with /investing
, such as /investing/projects
and so on.
After editing a page, Drupal helpfully redirects the user to node/[nodenumber]. For us, this means that the menu is no longer displayed and even the theme will be wrong. (We use the Sections module to select a subtheme based on which section you’re in.)
Global Redirect doesn’t work
The Global Redirect module promises to solve this by allowing you to redirect node/[nodenumber] URLs to their alias if available. It kinda does, in some circumstances.
Our Drupal website sports two languages: English (EN) and Dutch (NL). English is the default language (not the fallback language; we don’t use a fallback) and doesn’t use a prefix. Dutch uses the nl prefix. Two example URLs:
URL alias | Generic URL |
---|---|
http://www.example.com/investing/projects | http://www.example.com/node/288 |
http://www.example.com/nl/beleggen/projecten | http://www.example.com/nl/node/110 |
When /node/288 is requested, the client is correctly redirected to /investing/projects, but when /node/110 is requested, no redirect takes place. It will take place when prefixing /nl, but this is completely useless since Drupal’s built-in actions such as edit don’t redirect using this prefix, and these actions were what we needed this module for in the first place.
A very simple hack that does work
We ended up tearing our hair out trying to fix Global Redirect until we decided that we could just delete the module and replace it with a RewriteRule and a simple PHP script.
Modify: .htaccess
# Put this after RewriteBase and before Drupal's default rewrite rules RewriteRule ^(../)?node/([0-9]+)$ fixurl.php?nid=$2 [L]
Add: fixurl.php
<?php require_once './includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE); $result = db_query("SELECT * FROM {url_alias} WHERE src = 'node/%d' LIMIT 1", $_GET['nid']); if ( db_error() ) die("O agony!"); $url_alias_object = db_fetch_object($result); $destination = $url_alias_object->dst; $result = db_query("SELECT prefix FROM {languages} WHERE language = '%s'", $url_alias_object->language); if ( db_error() ) die("O agony!"); $prefix = db_result($result); if ( !empty($prefix) ) $prefix .= '/'; header("Location: /$prefix$destination",TRUE,301); ?>
Shortcomings in our hack
The code assumes that every content page has an URL alias. For us, this is okay, because we need these pretty URLs to even have menus show up or to have the right page be displayed with the right theme.
Also, this code is specifically tailored to language code in the URL prefix. For subdomain based language selection, for example, you’d need to modify it.
Recent Comments