Note: Terms used in this article.
- argument: as in arguments of a php function. And
- element means an argument of the path. Example: /node/224170/edit - 224170 is an element.
When a wildcard loader is utilized in a menu path, the value of the element at the position of the loader definition is passed to the wildcard loader function as the first argument.
$items['node/%node/revisions'] = array(
When a % symbol is used in a menu element (see example), the text that follows will be used to build the name of wildcard loader function.
In the example above, "%node" tells drupal to pass the value of the second element to the function node_load(). _load is always added by Drupal to construct the wildcard loader.
So, if you were to go to node/1337/revisions in your browser, then node_load(1337) would be called.
Multiple Wildcard Loader Arguments
Drupal will always execute the loader function with the first argument of the loader being the path element where the loader is defined. But what if we want to add custom arguments to the loader function?
To get Drupal to include another element of the path, such as a second wildcard, we need to use the “load arguments” menu item property.
Remember: the first argument is always going to be the value where the loader is defined, any arguments in "load arguments" will be 2nd, 3rd values etc. A better way to think of "load argument" is extra load arguments because the first argument is always assumed.
$items['node/%node/revisions/%/view'] = array(
'title' => 'Revisions',
'load arguments' => array(3), // HERE
'page callback' => 'drupal_get_form',
'page arguments' => array('node_revision_revert_confirm', 1),
'type' => MENU_CALLBACK,
The "load arguments" in the above example defines additional arguments to pass to the load function. By default, the load function (node_load() in this case) will only be passed part 1 (the text in position "%node" in this case) of the path.
If we want to pass a node revision to node_load() which is its second argument, we can define "load arguments" with additional arguments in an array. Positive integers in this array are handled specially; they're replaced with the part of the path in the corresponding position. In this example, 3 is replaced with part 3 (with counting beginning at zero) of the actual path when a user browses to the page. So, if we navigate to node/1337/revisions/42/view then node_load(1337,42) would be called.
As usual, the returned value of the loader function can then be used by the “access callback” or a “page callback” by including the element's index as an “access argument” or “page argument”. Using the example above, the returned value of node_load will be passed to the page callback like this:
Note: When using
drupal_get_form as the page callback, the first variable passed to the function is
function node_revision_revert_confirm($form_state, $node_revision ). So when you send arguments they will be available as second, third ... and so on.
Special Wildcard Loader Arguments
Using integers to get the path element substitute is very useful, but there are also ways to get even more information.
%map and %index
- %map: All elements of the path are converted to a keyed array. This is also a variable reference
- %index: The element of the path the wildcard loader is defined in.
$items['user/%user_category/edit'] = array(
'title' => 'Edit',
'page callback' => 'user_edit',
'page arguments' => array(1),
'access callback' => 'user_edit_access',
'access arguments' => array(1),
'type' => MENU_LOCAL_TASK,
'load arguments' => array('%map', '%index'),
'file' => 'user.pages.inc',
If we navigated to user/55/edit then user_category_load($uid, $map_array, $index) would be called.
The first argument of the loader function would be the integer 55.
The second argument of the loader would be
 => "user",
 => 55,
 => "edit",
The third argument of the loader would be the integer 1, because that is the position of the path that the loader was defined in.
If a wildcard loader function returns
FALSE it would be the equivalent of page not found.
If you want to look into how all this works, go to the _menu_load_objects function in includes/menu.inc