Mass URL aliasing

Last modified: December 4, 2008 - 18:26

Drupal also comes with user defined mass URL aliasing capabilities. You might like to see completely different URLs used by Drupal, or even URLs translated to the visitors' native language, in which case this feature is handy. Only an administrator with access to the website source code can set up this kind of aliases. You can define a function somewhere in your code (even in settings.php), following this example:

<?php
// Example for Drupal 4.6.x
function conf_url_rewrite($path, $mode = 'incoming') {
  if (
$mode == 'incoming') { // URL coming from a client
   
return preg_replace('!^display/(\d+)$!', 'node/\1', $path);
  }
  elseif (
$mode == 'outgoing') { // URL going out to a client
   
return preg_replace('!^node/(\d+)$!', 'display/\1', $path);
  }
}
?>

<?php
// Example for Drupal 4.7.x and 5.x (NOT 6.x)
function custom_url_rewrite($type, $path, $original) {
 
// This path was already aliased, skip rewriting it
 
if ($path != $original) {
    return
$path;
  }
  if (
$type == 'source') { // URL coming from a client
   
return preg_replace('!^display/(\d+)$!', 'node/\1', $path);
  }
  elseif (
$type == 'alias') { // URL going out to a client
   
return preg_replace('!^node/(\d+)$!', 'display/\1', $path);
  }
}
?>

This function will shorten every node/$node_id type of URL to display/$node_id. Individual URL aliases defined on the browser interface of Drupal take precedence, so if you have a 'contact' page alias for example, then the display/3 alias will not be effective when outgoing links are created. Incoming URLs however always work with the mass URL aliased variant. Only two modes are supposed to be supported by your custom function.

You cannot only use this feature to shorten the URLs, or to translate them to you own language, but also to add completely new subURLs to an already existing module's URL space, or to compose a bunch of existing stuff together to a common URL space. You can create a news section for example aliasing nodes and taxonomy overview pages falling under a 'news' vocabulary, thus having news/15 and news/sections/3 instead of node/15 and taxonomy/term/3. You need extensive knowledge of Drupal's inner workings and regular expressions though to make such advanced aliases.

Again, this is an advanced Drupal feature which requires more than basic PHP knowledge to use. For most users, pathauto and related modules will meet their needs, and they require no experience with PHP or regular expressions.

Settings.php

mfredrickson - February 2, 2006 - 16:44

I think it is important to note that (at least for 4.6 - I haven't seen 4.7 on this yet) you must put this function in your settings.php file.

I tried to put it in a module, but was met with some very confusing results (outgoing translations worked like a charm, incoming translations were horribly broken).

Here's why you need custom_url_rewrite in settings.php

_craig - October 22, 2006 - 20:03

Looking at the core drupal code (4.7.4), here's why custom_url_rewrite needs to be in settings.php.

  • index.php is the entry point for any page request and one of the first things it does is start the bootstrap process
  • As part of the bootstrap process, drupal sequentially goes through each of the bootstrap phases:
  • The alias -> drupal path conversion occurs during the DRUPAL_BOOTSTRAP_PATH phase. Module files are loaded in the DRUPAL_BOOTSTRAP_FULL phase. The DRUPAL_BOOTSTRAP_PATH phase occurs before DRUPAL_BOOTSTRAP_FULL. Therefore the path conversion takes place before any module files are loaded.

API documentation

beginner - May 18, 2007 - 09:32

Karoly just documented it at api.drupal.org:
http://api.drupal.org/api/HEAD/function/custom_url_rewrite
With more examples.

--
http://www.reuniting.info/
Healing with Sexual Relationships.
http://www.wechange.org/
We live in a world of solutions.

Updated links

mvc - November 26, 2007 - 21:51

My custom_url_rewrite

gonzalom - December 12, 2007 - 02:30

I looked in to the example in http://api.drupal.org/api/function/custom_url_rewrite/5

I change some thing and I get off the fourth arg "$path_language" because I got an error msg.

Finally, my function is:

<?php
function custom_url_rewrite($op, $result, $path) {
   
//global $user;
   
$items = array(
        array(
'source'=>'node',         'alias'=>'articulo',     'patron'=>'/^%item%(.*)$/',     'result'=>'%item%\1'),
        array(
'source'=>'taxonomy',     'alias'=>'categoria',     'patron'=>'/^%item%(.*)$/',     'result'=>'%item%\1'),
        array(
'source'=>'term',         'alias'=>'termino',     'patron'=>'/\/%item%\//',         'result'=>'/%item%/'),
        array(
'source'=>'user',         'alias'=>'usuario',     'patron'=>'/^%item%(.*)$/',     'result'=>'%item%\1'),
        array(
'source'=>'blog',         'alias'=>'blog',         'patron'=>'/^%item%(.*)$/',     'result'=>'%item%\1'),
        array(
'source'=>'forum',         'alias'=>'foro',         'patron'=>'/^%item%(.*)$/',     'result'=>'%item%\1'),
        array(
'source'=>'image',         'alias'=>'imagen',         'patron'=>'/^%item%(.*)$/',     'result'=>'%item%\1'),
        array(
'source'=>'aggregator',     'alias'=>'noticias',     'patron'=>'/^%item%(.*)$/',     'result'=>'%item%\1')
    );
    if (
$op == 'alias') {
       
// source to alias. Ej: node -> articulo
       
$reemplazos = array();
        foreach(
$items AS $item ) {
           
$key = str_replace('%item%',$item['source'],$item['patron']);
           
$value = str_replace('%item%',$item['alias'],$item['result']);
           
$reemplazos[$key] = $value;
        }
        return
preg_replace(array_keys($reemplazos), array_values($reemplazos), $path);
    }
    if (
$op == 'source') {
       
// alias to source. Ej: articulo -> node
       
$reemplazos = array();
        foreach(
$items AS $item ) {
           
$key = str_replace('%item%',$item['alias'],$item['patron']);
           
$value = str_replace('%item%',$item['source'],$item['result']);
           
$reemplazos[$key] = $value;
        }
        return
preg_replace(array_keys($reemplazos), array_values($reemplazos), $path);
    }
   
// Return the default result
   
return $result;
}
?>

As you can see, you can specify a pattern for each item.
The most common pattern is '/^%item%(.*)$/', that only get the item if is in the beginning, but you may be interested in other patterns: "term" (like in taxonomy/term/3) is not at the beginning of the string, so it will not work with the most common pattern, this item will need a pattern like '/\/%item%\//'.

Yo can add as many items as you want, and you can also write a module to put them all through the admin.

A sticky situation?

Trejkaz - December 3, 2008 - 06:11

What if I want all the nodes of one type to be aliased but not any of the other ones, so that articles for a knowledge base can be /kb/5 whereas nodes for something else can still be /node/6?

pathauto

Tectonic - December 3, 2008 - 06:18

You're talking about setting the aliases for all of the nodes of a particular Content Type to have one pattern, while the nodes of other content types default to a 2nd pattern?

If so the user interface of the pathauto module will do this for you, no coding required, and also make sure that all newly created nodes have their aliases set based upon the same rules.

 
 

Drupal is a registered trademark of Dries Buytaert.