You have two options.
This is based on pathauto, and will create additional aliases for node sub-pages.
This also works for other entity types such as user/123/contact -> people/geronimo/contact
, if user/123
has the alias people/geronimo
.
2. Write a custom wildcard loader (far more work).
I am going to use the word "slug" here, which I remember from Wordpress.
The usual node path is node/%node
, which will trigger the node_load()
wildcard loader. This wildcard loader only takes node ids. It does not work with node titles. So, node_load(123)
gets you the node with that id, but node_load('node title')
will return NULL.
You could now create a new module "mymodule", and use hook_menu()
to define a separate path article/%mymodule_article_slug
, and sub-paths article/%mymodule_article_slug/page
, article/%mymodule_article_slug/edit
, etc.
This is going to be some work, you need to look into node.module and the hook_menu()
implementation found there, and copy a lot from there. Or you could use hook_menu_alter()
instead of hook_menu()
, and copy some of the data already registered for node/%
and friends.
The essential trick now is to define a wildcard loader for %mymodule_article_slug
.
/**
* Wildcard loader callback for '%mymodule_article_slug'.
*
* @param string $slug
* Part of the url identifying the node, e.g. "pink-elephant"
* @return object|null
* The node object, usually an instance of stdClass, or
* NULL, if no such node exists.
*/
function mymodule_article_slug_load($slug) {
// Load the node identified by $slug.
$node = ...;
return $node;
}
Now it gets insteresting. How do you load the node identified by the "slug"?
There are different ways.
You could store the slug in a field on the node, and then use EntityFieldQuery to load the node with that field value. You also need to decide what to do if more than one node has the same slug.
You could use path + pathauto and find the node where the alias is "article/" . $slug
. drupal_get_normal_path()
can help you with that.
With method 2, your code would look like this:
function mymodule_article_slug_load($slug) {
// Load the node identified by $slug.
$normalpath = drupal_get_normal_path('article/' . $slug);
if ($normalpath && preg_match('#/node\/(\d+)$/', $normalpath, $m)) {
$nid = (int)$m[1];
if ($nid > 0) {
return node_load($nid);
}
}
}
EDIT: This only works if the "slug" does not contain any slashes by itself!
hook_menu()
question will answer this (and then some). As a hint you're looking to passpage arguments
to your callback function. Have a look at the section labelled Arguments in the linked answer$node
but it's not working yet... seems to load the /article view page that shows all articles, might be the view overriding it though.