欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

hook_menu 涉及百分号 % 有大用

路径中的通配符

简单的通配符

路径中的通配符也可以使用整数替换。例如,您的模块可以注册路径'my-module /%/ edit':

$items['my-module/%/edit'] = array(
  'page callback' => 'mymodule_abc_edit',
  'page arguments' => array(
    1,
  ),
);

当请求路径'my-module / foo / edit'时,整数1将被替换为'foo'并传递给回调函数。请注意,通配符不能用作第一个组件。

自动装载机通配符

注册路径还可能包含'%mymodule_abc'形式的特殊“自动加载器”通配符组件,其中'%'部分表示此路径组件是通配符,'mymodule_abc'部分定义加载函数的前缀,这里将命名为mymodule_abc_load()。当请求匹配路径时,您的加载函数将接收通配符位置中的路径组件作为其第一个参数; load函数也可以传递额外的参数(参见下面返回值部分中的“load arguments”)。例如,您的模块可以注册路径'my-module /%mymodule_abc / edit':

$items['my-module/%mymodule_abc/edit'] = array(
  'page callback' => 'mymodule_abc_edit',
  'page arguments' => array(
    1,
  ),
);

当请求路径'my-module / 123 / edit'时,你的加载函数mymodule_abc_load()将使用参数'123'调用,并且应该加载并返回一个内部id为123的“abc”对象:

function mymodule_abc_load($abc_id) {
  return db_query("SELECT * FROM {mymodule_abc} WHERE abc_id = :abc_id", array(
    ':abc_id' => $abc_id,
  ))
    ->fetchObject();
}

然后将这个'abc'对象传递给为菜单项定义的回调函数,例如页面回调函数mymodule_abc_edit(),以替换参数数组中的整数1。请注意,当加载函数无法提供可加载对象时,它应返回FALSE。例如,如果节点ID为999的节点不存在,则“node /%node / edit”菜单项node_load()函数将返回路径“node / 999 / edit”的FALSE。在这种情况下,菜单路由系统将返回404错误。

论证通配符

您还可以定义%wildcard_to_arg()函数(对于上面的示例菜单项,将是'mymodule_abc_to_arg()')。调用_to_arg()函数以检索路径中使用的值以代替通配符。一个很好的例子是user.module,它定义 user_uid_optional_to_arg()(对应于菜单项“跟踪器/%user_uid_optional”)。此函数返回当前用户的用户ID。

将使用三个参数调用_to_arg()函数:

  • $ ARG:代表任何说法可能已经被调用者提供的字符串(如果你想,如果没有指定其他值是_to_arg()函数只提供一个(默认)值,这是特别有用的,因为在案件user_uid_optional_to_arg() 。

  • $ map:所有路径片段的数组(例如,'node / 123 / edit'的数组('node','123','edit'))。

  • $ index:一个整数,指示$ map的哪个元素对应于$ arg。

_load()和_to_arg()函数乍一看似乎相似,但它们有不同的用途,并在不同的时间调用。当菜单系统收集参数以传递给为菜单项定义的回调函数时,将调用_load()函数。当菜单系统生成指向相关路径的链接时,会调用_to_arg()函数,例如一组MENU_LOCAL_TASK的选项卡

image.png

image.png

来自  https://api.drupal.org/api/drupal/modules!system!system.api.php/function/hook_menu/7.x




function hook_menu

Same name and namespace in other branches

Define menu items and page callbacks.

This hook enables modules to register paths in order to define how URL requests are handled. Paths may be registered for URL handling only, or they can register a link to be placed in a menu (usually the Navigation menu). A path and its associated information is commonly called a "menu router item". This hook is rarely called (for example, when modules are enabled), and its results are cached in the database.

hook_menu() implementations return an associative array whose keys define paths and whose values are an associative array of properties for each path. (The complete list of properties is in the return value section below.)

Callback Functions

The definition for each path may include a page callback function, which is invoked when the registered path is requested. If there is no other registered path that fits the requested path better, any further path components are passed to the callback function. For example, your module could register path 'abc/def':

function mymodule_menu() {
  $items['abc/def'] = array(
    'page callback' => 'mymodule_abc_view',
  );
  return $items;
}
function mymodule_abc_view($ghi = 0, $jkl = '') {

  // ...
}

When path 'abc/def' is requested, no further path components are in the request, and no additional arguments are passed to the callback function (so $ghi and $jkl would take the default values as defined in the function signature). When 'abc/def/123/foo' is requested, $ghi will be '123' and $jkl will be 'foo'. Note that this automatic passing of optional path arguments applies only to page and theme callback functions.

Callback Arguments

In addition to optional path arguments, the page callback and other callback functions may specify argument lists as arrays. These argument lists may contain both fixed/hard-coded argument values and integers that correspond to path components. When integers are used and the callback function is called, the corresponding path components will be substituted for the integers. That is, the integer 0 in an argument list will be replaced with the first path component, integer 1 with the second, and so on (path components are numbered starting from zero). To pass an integer without it being replaced with its respective path component, use the string value of the integer (e.g., '1') as the argument value. This substitution feature allows you to re-use a callback function for several different paths. For example:

function mymodule_menu() {
  $items['abc/def'] = array(
    'page callback' => 'mymodule_abc_view',
    'page arguments' => array(
      1,
      'foo',
    ),
  );
  return $items;
}

When path 'abc/def' is requested, the page callback function will get 'def' as the first argument and (always) 'foo' as the second argument.

If a page callback function uses an argument list array, and its path is requested with optional path arguments, then the list array's arguments are passed to the callback function first, followed by the optional path arguments. Using the above example, when path 'abc/def/bar/baz' is requested, mymodule_abc_view() will be called with 'def', 'foo', 'bar' and 'baz' as arguments, in that order.

Special care should be taken for the page callback drupal_get_form(), because your specific form callback function will always receive $form and &$form_state as the first function arguments:

function mymodule_abc_form($form, &$form_state) {

  // ...
  return $form;
}

See Form API documentation for details.

Wildcards in Paths

Simple Wildcards

Wildcards within paths also work with integer substitution. For example, your module could register path 'my-module/%/edit':

$items['my-module/%/edit'] = array(
  'page callback' => 'mymodule_abc_edit',
  'page arguments' => array(
    1,
  ),
);

When path 'my-module/foo/edit' is requested, integer 1 will be replaced with 'foo' and passed to the callback function. Note that wildcards may not be used as the first component.

Auto-Loader Wildcards

Registered paths may also contain special "auto-loader" wildcard components in the form of '%mymodule_abc', where the '%' part means that this path component is a wildcard, and the 'mymodule_abc' part defines the prefix for a load function, which here would be named mymodule_abc_load(). When a matching path is requested, your load function will receive as its first argument the path component in the position of the wildcard; load functions may also be passed additional arguments (see "load arguments" in the return value section below). For example, your module could register path 'my-module/%mymodule_abc/edit':

$items['my-module/%mymodule_abc/edit'] = array(
  'page callback' => 'mymodule_abc_edit',
  'page arguments' => array(
    1,
  ),
);

When path 'my-module/123/edit' is requested, your load function mymodule_abc_load() will be invoked with the argument '123', and should load and return an "abc" object with internal id 123:

function mymodule_abc_load($abc_id) {
  return db_query("SELECT * FROM {mymodule_abc} WHERE abc_id = :abc_id", array(
    ':abc_id' => $abc_id,
  ))
    ->fetchObject();
}

This 'abc' object will then be passed into the callback functions defined for the menu item, such as the page callback function mymodule_abc_edit() to replace the integer 1 in the argument array. Note that a load function should return FALSE when it is unable to provide a loadable object. For example, the node_load() function for the 'node/%node/edit' menu item will return FALSE for the path 'node/999/edit' if a node with a node ID of 999 does not exist. The menu routing system will return a 404 error in this case.

Argument Wildcards

You can also define a %wildcard_to_arg() function (for the example menu entry above this would be 'mymodule_abc_to_arg()'). The _to_arg() function is invoked to retrieve a value that is used in the path in place of the wildcard. A good example is user.module, which defines user_uid_optional_to_arg() (corresponding to the menu entry 'tracker/%user_uid_optional'). This function returns the user ID of the current user.

The _to_arg() function will get called with three arguments:

  • $arg: A string representing whatever argument may have been supplied by the caller (this is particularly useful if you want the _to_arg() function only supply a (default) value if no other value is specified, as in the case of user_uid_optional_to_arg().

  • $map: An array of all path fragments (e.g. array('node','123','edit') for 'node/123/edit').

  • $index: An integer indicating which element of $map corresponds to $arg.

_load() and _to_arg() functions may seem similar at first glance, but they have different purposes and are called at different times. _load() functions are called when the menu system is collecting arguments to pass to the callback functions defined for the menu item. _to_arg() functions are called when the menu system is generating links to related paths, such as the tabs for a set of MENU_LOCAL_TASK items.

Rendering Menu Items As Tabs

You can also make groups of menu items to be rendered (by default) as tabs on a page. To do that, first create one menu item of type MENU_NORMAL_ITEM, with your chosen path, such as 'foo'. Then duplicate that menu item, using a subdirectory path, such as 'foo/tab1', and changing the type to MENU_DEFAULT_LOCAL_TASK to make it the default tab for the group. Then add the additional tab items, with paths such as "foo/tab2" etc., with type MENU_LOCAL_TASK. Example:

// Make "Foo settings" appear on the admin Config page
$items['admin/config/system/foo'] = array(
  'title' => 'Foo settings',
  'type' => MENU_NORMAL_ITEM,
);

// Make "Tab 1" the main tab on the "Foo settings" page
$items['admin/config/system/foo/tab1'] = array(
  'title' => 'Tab 1',
  'type' => MENU_DEFAULT_LOCAL_TASK,
);

// Make an additional tab called "Tab 2" on "Foo settings"
$items['admin/config/system/foo/tab2'] = array(
  'title' => 'Tab 2',
  'type' => MENU_LOCAL_TASK,
);

Return value

An array of menu items. Each menu item has a key corresponding to the Drupal path being registered. The corresponding array value is an associative array that may contain the following key-value pairs:

  • "title": Required. The untranslated title of the menu item.

  • "title callback": Function to generate the title; defaults to t(). If you require only the raw string to be output, set this to FALSE.

  • "title arguments": Arguments to send to t() or your custom callback, with path component substitution as described above.

  • "description": The untranslated description of the menu item.

  • "page callback": The function to call to display a web page when the user visits the path. If omitted, the parent menu item's callback will be used instead.

  • "page arguments": An array of arguments to pass to the page callback function, with path component substitution as described above.

  • "delivery callback": The function to call to package the result of the page callback function and send it to the browser. Defaults to drupal_deliver_html_page() unless a value is inherited from a parent menu item. Note that this function is called even if the access checks fail, so any custom delivery callback function should take that into account. See drupal_deliver_html_page() for an example.

  • "access callback": A function returning TRUE if the user has access rights to this menu item, and FALSE if not. It can also be a boolean constant instead of a function, and you can also use numeric values (will be cast to boolean). Defaults to user_access() unless a value is inherited from the parent menu item; only MENU_DEFAULT_LOCAL_TASK items can inherit access callbacks. To use the user_access() default callback, you must specify the permission to check as 'access arguments' (see below).

  • "access arguments": An array of arguments to pass to the access callback function, with path component substitution as described above. If the access callback is inherited (see above), the access arguments will be inherited with it, unless overridden in the child menu item.

  • "theme callback": (optional) A function returning the machine-readable name of the theme that will be used to render the page. If not provided, the value will be inherited from a parent menu item. If there is no theme callback, or if the function does not return the name of a current active theme on the site, the theme for this page will be determined by either hook_custom_theme() or the default theme instead. As a general rule, the use of theme callback functions should be limited to pages whose functionality is very closely tied to a particular theme, since they can only be overridden by modules which specifically target those pages in hook_menu_alter(). Modules implementing more generic theme switching functionality (for example, a module which allows the theme to be set dynamically based on the current user's role) should usehook_custom_theme() instead.

  • "theme arguments": An array of arguments to pass to the theme callback function, with path component substitution as described above.

  • "file": A file that will be included before the page callback is called; this allows page callback functions to be in separate files. The file should be relative to the implementing module's directory unless otherwise specified by the "file path" option. Does not apply to other callbacks (only page callback).

  • "file path": The path to the directory containing the file specified in "file". This defaults to the path to the module implementing the hook.

  • "load arguments": An array of arguments to be passed to each of the wildcard object loaders in the path, after the path argument itself. For example, if a module registers path node/%node/revisions/%/view with load arguments set to array(3), the '%node' in the path indicates that the loader function node_load() will be called with the second path component as the first argument. The 3 in the load arguments indicates that the fourth path component will also be passed to node_load() (numbering of path components starts at zero). So, if path node/12/revisions/29/view is requested, node_load(12, 29) will be called. There are also two "magic" values that can be used in load arguments. "%index" indicates the index of the wildcard path component. "%map" indicates the path components as an array. For example, if a module registers for several paths of the form 'user/%user_category/edit/*', all of them can use the same load function user_category_load(), by setting the load arguments to array('%map', '%index'). For instance, if the user is editing category 'foo' by requesting path 'user/32/edit/foo', the load function user_category_load() will be called with 32 as its first argument, the array ('user', 32, 'edit', 'foo') as the map argument, and 1 as the index argument (because %user_category is the second path component and numbering starts at zero). user_category_load() can then use these values to extract the information that 'foo' is the category being requested.

  • "weight": An integer that determines the relative position of items in the menu; higher-weighted items sink. Defaults to 0. Menu items with the same weight are ordered alphabetically.

  • "menu_name": Optional. Set this to a custom menu if you don't want your item to be placed in Navigation.

  • "expanded": Optional. If set to TRUE, and if a menu link is provided for this menu item (as a result of other properties), then the menu link is always expanded, equivalent to its 'always expanded' checkbox being set in the UI.

  • "context": (optional) Defines the context a tab may appear in. By default, all tabs are only displayed as local tasks when being rendered in a page context. All tabs that should be accessible as contextual links in page region containers outside of the parent menu item's primary page context should be registered using one of the following contexts:


    Contexts can be combined. For example, to display a tab both on a page and inline, a menu router item may specify:

    • MENU_CONTEXT_PAGE: (default) The tab is displayed as local task for the page context only.

    • MENU_CONTEXT_INLINE: The tab is displayed as contextual link outside of the primary page context only.


      'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
    
  • "tab_parent": For local task menu items, the path of the task's parent item; defaults to the same path without the last component (e.g., the default parent for 'admin/people/create' is 'admin/people').

  • "tab_root": For local task menu items, the path of the closest non-tab item; same default as "tab_parent".

  • "position": Position of the block ('left' or 'right') on the system administration page for this item.

  • "type": A bitmask of flags describing properties of the menu item. Many shortcut bitmasks are provided as constants in menu.inc:


    If the "type" element is omitted, MENU_NORMAL_ITEM is assumed.

    • MENU_NORMAL_ITEM: Normal menu items show up in the menu tree and can be moved/hidden by the administrator.

    • MENU_CALLBACK: Callbacks simply register a path so that the correct information is generated when the path is accessed.

    • MENU_SUGGESTED_ITEM: Modules may "suggest" menu items that the administrator may enable.

    • MENU_LOCAL_ACTION: Local actions are menu items that describe actions on the parent item such as adding a new user or block, and are rendered in the action-links list in your theme.

    • MENU_LOCAL_TASK: Local tasks are menu items that describe different displays of data, and are generally rendered as tabs.

    • MENU_DEFAULT_LOCAL_TASK: Every set of local tasks should provide one "default" task, which should display the same page as the parent item.

  • "options": An array of options to be passed to l() when generating a link from this menu item. Note that the "options" parameter has no effect on MENU_LOCAL_TASKMENU_DEFAULT_LOCAL_TASK, and MENU_LOCAL_ACTION items.

For a detailed usage example, see page_example.module. For comprehensive documentation on the menu system, see http://drupal.org/node/102338.

Related topics

63 functions implement hook_menu()

File


  • modules/

    system/

    system.api.php, line 1264

  • Hooks provided by Drupal core and the System module.


Code

function hook_menu() {
  $items['example'] = array(
    'title' => 'Example Page',
    'page callback' => 'example_page',
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_SUGGESTED_ITEM,
  );
  $items['example/feed'] = array(
    'title' => 'Example RSS feed',
    'page callback' => 'example_feed',
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

Comments

rszrama’s picture

In your menu item definitions, you can specify TRUE as the access callback to make the item always accessible.

See http://api.drupal.org/api/function/_menu_check_access/7.

drclaw’s picture

The other day, I was trying to create a menu item with a dynamically generated path and hit a couple road blocks. After some reading I eventually worked it out and thought I would post an example here. It all came down to the wildcards and how to handle them. I was using a local task menu item as an example at first, but soon figured out that the wildcard technique for local tasks are quite a bit different than normal menu items...

These are all the readings I used to compile *some* understanding of the menu system:

Api Docs
Drupal Menu System Overview:
Dynamic Menu Argument replacement. This one is Good!
Wildcard usage and core's wildcards This one also has the full list of all the existing wildcard loaders for D6 (probably similar for D7)
http://api.drupal.org/api/function/page_example_menu
http://api.drupal.org/api/group/menu

Google Books:
Pro Drupal Development Chapter 4 - The Menu System

<?php

function time_sheet_menu() {
  $items = array();
  // This one creates a 'tab' (local task) when on a page whose URL matches the format:
  // 'user/%user/profile'. The syntax for %user is indicating two things:
  //   - '%' Represents a wild card (in this case we're looking for a user id)
  //   - 'user' Represents which wildcard loader to use ( user_load(%) )
  //        There are a finite number of wildcard loaders which can be seen at
  //        http://drupal.org/node/209056 (you will need to scroll down a bit)
  // What happens is:
  // 1) A tab is created on any path that matches user/%/profile (e.g. user/38/profile)
  // 2) When the link is clicked, profile_user_page() is called...
  // 3) The argument passed into profile_user_page() is the result of user_load(38)
  //     -- 'page arguments' gets an array passed in indicating which 
  //         part of the path should be used for the callback args.
  //         Assuming the path www.example.com/user/38/profile could have its path 
  //         numbered www.example.com/[0]/[1]/[2], array(1) is referring to the second
  //         item in the path after the base. In our case the number 38
  $items['user/%user/profile'] = array(
    'title' => 'Profile',
    'description' => 'My Profile',
    'page callback' => 'profile_user_page', // the function to be called when link is clicked [below]
    'page arguments' => array(1), // arguments for the callback function 'profile_use_page'
    'access arguments' => array('view own profile'), // permission
    'type' => MENU_LOCAL_TASK,
  );
  // In this example, we are creating a actual menu item with a dynamically generated path. 
  // Givens: A menu item will be added to the 'my_menu' menu,
  // with the text 'Profile', pointing to profile/[the_current_users_id]
  // How the path is generated:
  // 1) The %currentuser wildcard is actually calling the function: 
  //    currentuser_to_arg (defined after this function) because currentuser_load()
  //    is not in the list of existing wildcard loaders. The wildcard will be passed
  //    to the function: currentuser_to_arg(%)
  // 2) The currentuser_to_arg() [below] function runs and returns the user id
  // 3) The user id is passed as a argument into the time_sheet_user_page() callback
  //    using the same technique as the above example
  $items['profile/%currentuser'] = array(
    'title' => 'Profile', // The link text
    'description' => 'My Profile',
    'page callback' => 'profile_user_page', // the function to be called when link is clicked [below]
    'page arguments' => array(1), // arguments for the callback function 'profile_use_page'
    'access arguments' => array('view own profile'),
    'type' => MENU_NORMAL_ITEM,
    'menu_name' => 'my_menu', // You'll need to have a menu named my_menu for this to work
                              // If not specified, it will default to 'navigation'
  );
  // Just remember that a "MENU_CALLBACK" is really just telling
  // drupal what to do if that particular path is requested
  // It doesn't create menu items.
  $items['user/add_user'] = array(
    'page callback' => 'add_new_user_form', // the function to be called when link is clicked [below]
    'access arguments' => array('create new users'), // permission?
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Helper function to dynamically enter the current user
 * into the path of the 'Profile' link in the my_menu menu
 */
function currentuser_to_arg($arg) {
  global $user;
  return $user->uid;
}

/**
 * A user's profile page
 *
 * @param $user_id
 * The user id of the user whose profile page will be laoded
 */
function profile_user_page($user_id) {
  // Enter your code here
}

/**
 * The form for adding a new User
 */
function add_new_user_form() {
  // Create a form here
  return $form
}

?>
Dave Cohen’s picture

In Drupal 6.x, menu items of type MENU_CALLBACK honor the title attribute. In 7.x, you'll find these items have a title like "Home". You can get something like the 6.x behavior by specifying type MENU_VISIBLE_IN_BREADCRUMB

I thought this worth mentioning, even if it is already documented.

weboide’s picture

If you want the menu item to show in the Main menu instead of the navigation, just set menu_name to 'main-menu', like so:

function mymodule_menu(){
  $items['mypage'] = array(
    'title' => 'Page name',
    'description' => t('Some page'),
    /* ... */
    'menu_name' => 'main-menu',
    /* ... */
  );
  return $items;
}
aethr’s picture

Additionally, you can specify a 'plid' of the parent menu item if you don't want your menu item to appear at the root of the specified menu.

function mymodule_menu(){
  $items['mypage'] = array(
    'title' => 'Page name',
    'description' => t('Some page'),
    /* ... */
    'menu_name' => 'main-menu',
    'plid' => 1234, // 'mlid' of parent item
    /* ... */
  );
  return $items;
}
mortona2k’s picture

in page_example.module, there is an $items variable with 'expanded' => TRUE, which isn't mentioned on this page or in the module:

 $items['examples/page_example'] = array(
    'title' => 'Page Example',
    'page callback' => 'page_example_description',
    'access callback' => TRUE,
    'expanded' => TRUE,
  ); 
esnyder’s picture

Not in the code above a small comment line:

// Need to add access callback or access arguments.

in the code for tabs:

// Make an additional tab called "Node settings" on "Foo settings"
$items['admin/config/foo/node'] = array(
'title' => 'Node settings',
'type' => MENU_LOCAL_TASK,
// Page callback and theme callback will be inherited from
// 'admin/config/foo', if not specified here to override.
// Need to add access callback or access arguments.
);

If you are having trouble with tabs not showing up using the code above you may need to add the access callback or access arguments as it says above.

dago.aceves’s picture

If you are adding menu items that you would like to come up in a modal overlay, or in a different theme), you'll need to also implement hook_admin_paths().

This should only be required if you are using a path other than something that starts with "admin", as Drupal by default adds the path "admin/*" in system_admin_paths().

Arla’s picture

If you (like me) happen to do a faulty implementation of hook_menu and your site crashes and gives only 404 not found for all pages, try this: "Page Not Found" error on ALL pages of Drupal 6 website

sreynen’s picture

Warning: using l() in descriptions will cause an infinite loop in Drupal core 7.7 and later. Using url() is safe.

zhangtaihao’s picture

This is because Drupal 7 now uses the theme registry to render links, where Drupal 6 renders them inline.

There is, however, a workaround. The documentation for l() states that edge cases can prevent theme initialization and force inline link rendering. Example:

/**
 * Implements hook_menu().
 */
function yourmodule_menu() {
  variable_set('theme_link', FALSE);
  $items = array();

  // ... Add to $items, use l() to construct links

  variable_del('theme_link');
  return $items;
}

This variable can in fact be used anywhere using l() causes an infinite loop due to an uninitialized theme registry.

Xano’s picture

Note that the include file is not only loaded for the page callback, but for the title callback as well.

roderik’s picture

Just a note: if you put the title callback in that include file, and it starts disappearing... it's probably because of some other module doing menu stuff in a hook_init() implementation.

ykhadilkar’s picture

Menu Access callback function gets called multiple time and sometimes even if you are not accessing corresponding menu item. Thats why dont alter anything in access callback function, just check if user can access the menu. You can place all that code in page callback.

meladawy’s picture

Add menu block container in administrator configuration page
http://drupalst.com/blog/add-menu-block-administrator-configuration-page

/**
* Implementation of hook_menu
*/
function drupalst_blocks_menu() {
 
	$menu['admin/config/drupalst'] =  array(  // this is the block that contain another configuration links
		'title' => t('DRUPALST') , 
		'description' => t('Drupalst tools') , 
		'weight' => -8, 		
		'page callback' => 'system_admin_menu_block_page',  // we should implement this function in system.admin.inc file
		'access arguments' => array('access administration pages'), 
		'file' => 'system.admin.inc',	 // don't forget to add the file and path
		'file path' => drupal_get_path('module', 'system'),
		'position' => 'right', 
	); 
 
	$menu['admin/config/drupalst/blocks'] = array( // this is an example of configuration link
		'title' => t('Drupalst blocks') , 
		'description' => t('Add themed blocks to drupalst themes') , 
		'page callback' => '_drupalst_blocks_generator' , 		
		'type' => MENU_NORMAL_ITEM, 
		'access arguments' => array('administer site configuration') ,
	); 
 
	return $menu ; 	
}
mcrittenden’s picture

Note that the title should be *untranslated* meaning that you shouldn't use t() for the title text.

hinikato’s picture

There is a awesome 'controller' module: http://drupal.org/node/1389042
that allows to write something like this one without adding your rules in the hook_menu():

class MySuperControllerController {
  /**
   * @path => 'admin/config/controller',
   * @access arguments => array(CONTROLLER_CHANGE_SETTINGS_PERM),
   * @title => 'Controller',
   * @default => array('default' => 'Settings'),
   */
  public function indexAction() {
    require_once drupal_get_path('module', 'controller') . '/forms/settings_form.inc';
    return drupal_get_form('controller_settings_form');
  }

  /**
   * @path => 'admin/config/controller/hook-menu'
   * @access arguments => array(CONTROLLER_CHANGE_SETTINGS_PERM),
   * @title => 'Show hook_menu()',
   * @type => MENU_LOCAL_TASK,
   * @weight => 2,
   */
  public function exportAction() {
    require_once drupal_get_path('module', 'controller') . '/forms/export_form.inc';
    return drupal_get_form('controller_export_form');
  } 
...
}
zifiniti’s picture

I was having trouble getting a menu item to display with the following code:

<?php
function mymodule_menu() {
  $items['custom-page'] = array(
    'title' => 'Custom Page',
    'menu_name' => 'main-menu',
    'access arguments' => array('access custom pages')
  );
?>

It was continuously denying me access to the specified path in addition to not displaying the item in the menu. I discovered that the reason behind this is if you do not specify a page callback, then the access callback will acquire a value of 0 in the database and thus render that path/menu item inaccessible.

Working code:

<?php
function mymodule_menu() {
  $items['custom-page'] = array(
    'title' => 'Custom Page',
    'menu_name' => 'main-menu',
    'page callback' => 'mymodule_custom_page',
    'access arguments' => array('access custom pages')
  );
?>
bstoppel’s picture

From what I can determine, using a uid in a path to access a different users profiles or other user paths only works if the menu type is MENU_LOCAL_TASK. I tried MENU_NORMAL_ITEM to no avail.

This works

$items['user/%user/profile'] = array(
    'title' => 'Profile',
    'page callback' => 'profile_user_page',
    'page arguments' => array(1),
    'access arguments' => array('view own profile'),
    'type' => MENU_LOCAL_TASK,
);

This doesn't work

$items['user/%user/profile'] = array(
    'title' => 'Profile',
    'page callback' => 'profile_user_page',
    'page arguments' => array(1),
    'access arguments' => array('view own profile'),
    'type' => MENU_NORMAL_ITEM,
);

This blog post contains a potential solution that works, but doesn't seem to work with path aliases. http://yuriybabenko.com/blog/using-user-id-arguments-in-drupal-menu-items

luxpaparazzi’s picture

Hi, i was desperately searching for how to change the title on a custom page, thx to IRC someone told me to use: drupal_set_title:

http://api.drupal.org/api/drupal/includes!bootstrap.inc/function/drupal_...

fxarte’s picture

When changed 'title_callback' and 'title_arguments' in hook_menu_get_item_alter(), I had to serialize the array in 'title_arguments'.


function MY_MODULE_menu_get_item_alter(&$router_item, $path, $original_map){
  if ($my_condition) {
      $router_item['title_callback'] = 'MY_MODULE_custom_menu_title';
      $router_item['title_arguments'] = serialize(array(1,'reference_value'));
  }
}
yol1982’s picture

Posting this to help other people as I had a hard time figuring it out myself.

The wildcard name set in the $item array key (%edit_example) is used
to trigger a function with the same name with _load suffix(edit_example_load()) automagically and will send the argument as parameter to this function.

Use the load function to check if the item you want to edit exists.
If load function returns false the form function(edit_example_form()) in "page arguments" is not called and an "page not found" will appear instead.
If not return false the return value will be the third parameter in the form function.

The number after the first "page argument"(The second "page argument") is pointing at wildcard in $item array key (represented by number if splitted by / like this 0/1/2/3/4/5)), i have not figured out why yet.

Totally logic!!! :D

function edit_example_menu() {
  $items['admin/config/system/edit_example/edit/%edit_example'] = array(
    'title' => t('Edit example'),
    'description' => t('Example of edit'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('edit_example_form', 5),
    'access arguments' => array('access administration pages'),
  );
}
  
function edit_example_load($example_id) {
  // Check if id item exist and return false to stop call to form function.
  // No use to edit non existing stuff
  return true;
}

function edit_example_form($form, &$form_state, $example_id) {
  //fill your form with data from exemple_id item
}
vlad.dancer’s picture

Thx a lot! It's very helpfull for me. But also i had some warning Notice: Undefined offset: 2 in _menu_translate()  and fixed like in Undefined offset: 2 in _menu_translate

kingandy’s picture

On a side note, you should NOT be using t() in your menu declarations. Menu automatically pushes title and description through t(), you'll end up with things being double-translated...

function edit_example_menu() {
  $items['admin/config/system/edit_example/edit/%edit_example'] = array(
    'title' => 'Edit example',
    'description' => 'Example of edit',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('edit_example_form', 5),
    'access arguments' => array('access administration pages'),
  );
}
thelee’s picture

A) The path must be valid for it to show up in the menu. I struggled for a long time in creating a placeholder like this:

function foo_menu() {
   // '/foo' doesn't exist yet
  $items['foo'] => array( 'title' => 'foo', 'description' => 'bar');
  return $items;
}

and wondering why no entry would be created. Looks like there's a validation step when hook_menu() runs.

B) The wildcard MUST begin with a letter. I was trying to stick to a convention of having _modulename as the prefix for functions that aren't directly implementing or creating a hook, like this:

function foo_menu() {
  $items['foo/%_foo'] => array( 'title' => 'foo', 'description' => 'bar');
  return $items;
}

function _foo_to_arg() { /* do something */ }

But drupal will silently fail on the %_foo wildcard without any indication otherwise.

C) God forbid you ever accidentally create an empty path  $items[''] =  or something that evaluates to an empty path  $items[''] = /* for some reason this turns into an empty path */  You will never be able to get rid of this menu item once created, due to some NULL checks, no matter how many times you rebuild menu/clear cache/remove module/etc. the only fix in this situation is to manually find the menu entry in your sql database (table: menu_links i think) and deleting it.

Reno Greenleaf’s picture

I use drupal_json_output as delivery callback. But this isn't normal practice for the system. Should I expect problems?

laghalt’s picture

In Drupal 7 the pagetitle does not work for MENU_LOCAL_TASK and perhaps MENU_CALLBACK,

http://alastaira.wordpress.com/2011/01/18/drupal-7-x-hook_menu-not-displ...

The title of a page turns to "Home".

The workaround in this post is to use MENU_VISIBLE_IN_BREADCRUMB instead.

matthias_mo’s picture

I had the same problem with MENU_DEFAULT_LOCAL_TASK and MENU_LOCAL_TASK items.

My solution was to add this line in the 'page callback' function:

function my_page_callback() {
 drupal_set_title(t('My page title'), PASS_THROUGH);
 ...;
}

nicholasstuartwilson’s picture

Thanks for the plid reminder!

Looking at the menu entry in the menu-links table shows that despite clearing the cache this setting is not necessarily picked up. In fact, it only registered when I changed the name and title of my menu item and proceeded to clear the cache.

I could have just updated directly in the database table myself but I mention this as perhaps something's amiss in the way hook_menu is read and passed to the database table?

wsmith77’s picture

Per the doc:
"options": An array of options to be passed to l() when generating a link from this menu item. Note that the "options" parameter has no effect on MENU_LOCAL_TASK, MENU_DEFAULT_LOCAL_TASK, and MENU_LOCAL_ACTION items.

I "should" be able to set "html" => true here and have l() not strip out the html. This does not work. My menu item is a MENU_NORMAL_ITEM so I don't see any reason for this not to work.

Tracing the code on a menu router rebuild, I see the property peristing through _menu_link_build. I do not see where this option is stored anywhere in the menu tables though. Options under menu_links just has the title attribute.

I put a breakpoint on every call to l() in menu.inc and I can see where my menu item is build, however I do not see where the options specified in the menu item are making it into the localized_options array that is passed into the l() call.

Is anyone else using this feature? I'm running 7.22.

wsmith77’s picture

after a day and a half I found the issue... my options key had a pesky tab after it... so the issue was due to my fat fingers...

hatuhay’s picture

The "delivery callback" function is very powerfull but it is not documented.

By default it calls the drupal_deliver_html_page() function, that returns a full rendered HTML page, including, header, footer, blocks, etc.

For webservices applications Drupal provides a json output using the ajax_deliver() function.

This function is very easy to manipulate, for example if you want your call to return just the content of your page without headers, footers and so, just use the following function:

<?php
function MyModule_content_callback($page_callback_result) {
  print drupal_render($page_callback_result);
  // Perform end-of-request tasks.
  drupal_page_footer();
}
?>

This one could be used as response for jQuery.load().

anand_babu’s picture

Here i have created the menu and sub link for the menu , it's created but it shows only menu, not a sub link of menu .

I want display the sub link of menu

function mymodule_coupon_menu() {
$menu_items['admin/mymodule'] = array(
'title' => 'mymodule',
'callback' => 'drupal_goto',
'page arguments' => array('admin/mymodule'),
'access arguments' => array('wandisco coupon'),
'weight' => 15,
'expanded' => TRUE,
'type' => MENU_NORMAL_ITEM,
);
$menu_items['admin/mymodule/coupon'] = array(
'title' => t('mymodule coupon'),
'page callback' => 'drupal_get_form',
'page arguments' => array('admin/mymodule/coupon'),
'access arguments' => array('mymodule coupon'),
'weight' => 0,
'expanded' => TRUE,
'type' => MENU_NORMAL_ITEM,
);

return $menu_items;
}

Bram Esposito’s picture

If you happen to call arg(X) within the callback function, and the argument is not set, a "Page not found" page will be displayed instead.

So when you're desperate after a few menu_rebuild()'s, flushing cache and maybe even rebuild via menu_rebuild(), just check your code for this.

Elijah Lynn’s picture

From https://api.drupal.org/api/drupal/includes!common.inc/function/drupal_de...

The page callback function can return one of:

  • NULL: to indicate no content.

  • An integer menu status constant: to indicate an error condition.

  • A string of HTML content.

  • A renderable array of content.

Returning a renderable array rather than a string of HTML is preferred, because that provides modules with more flexibility in customizing the final result.

mikegodin’s picture

The structure of that renderable array is somewhat described here:
https://www.drupal.org/node/930760

vegantriathlete’s picture

dagomar’s picture

I wanted a menu item to show up both as MENU_LOCAL_TASK and MENU_NORMAL_ITEM. This can be achieved with a pipe delimiter! Like so:

'type' => MENU_LOCAL_TASK | MENU_NORMAL_ITEM,

nishant.nikky’s picture

i create a custom frontpage page--frontpage.tpl.php... Actually i want to create a menu tab dynamically.. i try this " print drupal_render($main_menu_tree);" but not work in custom page.. Please help me....

jdgp77’s picture

Este modulo nos permite crear el contenido en una ruta, por ejemplo si la ruta es 'propiedad/la_mia', un ejemplo seria:

in the file:
standart.module

function standart_menu() {
  $items = array();
  $items['propiedad/la_mia'] = array(
    'title' => 'The best property',
    'page callback' => 'nombrefuncionavizualizar',
  );
  return $items;
}

//  YO tecomiendo que las funciones dentro de un modulo, tengan el nombre del modulo
//  standart_nombrefuncionavizualizar
function nombrefuncionavizualizar()
{
  return 'La mejor';
}
Bohus Ulrych’s picture

This took me some to figure out so maybe it could help to someone else.
I wanted to allow access to the users from some Roles.

I has to write access arguments this way:

'access callback' => 'user_has_role',
'access arguments' => array(array('Role 1', 'Role 2')),

Then my validation function looks looks like this:

function user_has_role($roles) {
    if (user_is_logged_in()) {
        global $user;
        if (in_array('administrator', $user->roles)) {
            return TRUE;
        }
        foreach ($roles as $role) {
            if (in_array($role, $user->roles)) {
                return TRUE;
            }
        }
    }
    else {
        return FALSE;
    }
}
kingandy’s picture

FWIW user_has_role is an existing function so don't call your function that. On the other hand, user_has_role () does return a boolean so can totally be used as an access function - but only for a single role ID. So you'd be able to do something like this:

    'access callback' => 'user_has_role',
    'access arguments' => array('1'),

Note use of the string value '1' per the documentation on Callback arguments above: "To pass an integer without it being replaced with its respective path component, use the string value of the integer (e.g., '1') as the argument value."

shiv.godi’s picture

This look like a typo:

'mymodule_abc_to_arg()' should be '%mymodule_abc_to_arg()'

kingandy’s picture

No, the "%wildcard" has been correctly replaced with the module name "mymodule". Function names cannot include punctuation.

If you do come across a typo in the docs please file an issue where it will receive the attention of the team responsible.

thlo7777’s picture

You might can't get effect just set weight for menu and sub menu until you clear cache.

cristiroma’s picture

Some of the examples above are using t() for title like 'title' => t('Title').
These will result in calling t() twice and you will end up with translated strings in the locales_source table because Drupal will call t(t('Title')).

alberto56’s picture

In some cases, to avoid the Object of class stdClass could not be converted to int , you might want to put 'page callback', 'page arguments', 'access callback', and 'access arguments' near the end of your item list. For example, this commit to the Nodequeue module was required to work around that notice.

kingandy’s picture

Looks like the important thing there is putting 'access callback' after 'page callback', and maybe 'access arguments' after 'access callback', but I could be wrong.

j. ayen green’s picture

1. Clear cache
2. Make sure your hook_menu ends with a return:
return $items;

Pages

  • 1

  •  

  • 2

  •  

  • next ›

  •  

  • last »

  • function hook_menu

  • Same name and namespace in other branches

    Define menu items and page callbacks.

    This hook enables modules to register paths in order to define how URL requests are handled. Paths may be registered for URL handling only, or they can register a link to be placed in a menu (usually the Navigation menu). A path and its associated information is commonly called a "menu router item". This hook is rarely called (for example, when modules are enabled), and its results are cached in the database.

    hook_menu() implementations return an associative array whose keys define paths and whose values are an associative array of properties for each path. (The complete list of properties is in the return value section below.)

    Callback Functions

    The definition for each path may include a page callback function, which is invoked when the registered path is requested. If there is no other registered path that fits the requested path better, any further path components are passed to the callback function. For example, your module could register path 'abc/def':

    function mymodule_menu() {
      $items['abc/def'] = array(
        'page callback' => 'mymodule_abc_view',
      );
      return $items;
    }
    function mymodule_abc_view($ghi = 0, $jkl = '') {
    
      // ...
    }

    When path 'abc/def' is requested, no further path components are in the request, and no additional arguments are passed to the callback function (so $ghi and $jkl would take the default values as defined in the function signature). When 'abc/def/123/foo' is requested, $ghi will be '123' and $jkl will be 'foo'. Note that this automatic passing of optional path arguments applies only to page and theme callback functions.

    Callback Arguments

    In addition to optional path arguments, the page callback and other callback functions may specify argument lists as arrays. These argument lists may contain both fixed/hard-coded argument values and integers that correspond to path components. When integers are used and the callback function is called, the corresponding path components will be substituted for the integers. That is, the integer 0 in an argument list will be replaced with the first path component, integer 1 with the second, and so on (path components are numbered starting from zero). To pass an integer without it being replaced with its respective path component, use the string value of the integer (e.g., '1') as the argument value. This substitution feature allows you to re-use a callback function for several different paths. For example:

    function mymodule_menu() {
      $items['abc/def'] = array(
        'page callback' => 'mymodule_abc_view',
        'page arguments' => array(
          1,
          'foo',
        ),
      );
      return $items;
    }

    When path 'abc/def' is requested, the page callback function will get 'def' as the first argument and (always) 'foo' as the second argument.

    If a page callback function uses an argument list array, and its path is requested with optional path arguments, then the list array's arguments are passed to the callback function first, followed by the optional path arguments. Using the above example, when path 'abc/def/bar/baz' is requested, mymodule_abc_view() will be called with 'def', 'foo', 'bar' and 'baz' as arguments, in that order.

    Special care should be taken for the page callback drupal_get_form(), because your specific form callback function will always receive $form and &$form_state as the first function arguments:

    function mymodule_abc_form($form, &$form_state) {
    
      // ...
      return $form;
    }

    See Form API documentation for details.

    Wildcards in Paths

    Simple Wildcards

    Wildcards within paths also work with integer substitution. For example, your module could register path 'my-module/%/edit':

    $items['my-module/%/edit'] = array(
      'page callback' => 'mymodule_abc_edit',
      'page arguments' => array(
        1,
      ),
    );

    When path 'my-module/foo/edit' is requested, integer 1 will be replaced with 'foo' and passed to the callback function. Note that wildcards may not be used as the first component.

    Auto-Loader Wildcards

    Registered paths may also contain special "auto-loader" wildcard components in the form of '%mymodule_abc', where the '%' part means that this path component is a wildcard, and the 'mymodule_abc' part defines the prefix for a load function, which here would be named mymodule_abc_load(). When a matching path is requested, your load function will receive as its first argument the path component in the position of the wildcard; load functions may also be passed additional arguments (see "load arguments" in the return value section below). For example, your module could register path 'my-module/%mymodule_abc/edit':

    $items['my-module/%mymodule_abc/edit'] = array(
      'page callback' => 'mymodule_abc_edit',
      'page arguments' => array(
        1,
      ),
    );

    When path 'my-module/123/edit' is requested, your load function mymodule_abc_load() will be invoked with the argument '123', and should load and return an "abc" object with internal id 123:

    function mymodule_abc_load($abc_id) {
      return db_query("SELECT * FROM {mymodule_abc} WHERE abc_id = :abc_id", array(
        ':abc_id' => $abc_id,
      ))
        ->fetchObject();
    }

    This 'abc' object will then be passed into the callback functions defined for the menu item, such as the page callback function mymodule_abc_edit() to replace the integer 1 in the argument array. Note that a load function should return FALSE when it is unable to provide a loadable object. For example, the node_load() function for the 'node/%node/edit' menu item will return FALSE for the path 'node/999/edit' if a node with a node ID of 999 does not exist. The menu routing system will return a 404 error in this case.

    Argument Wildcards

    You can also define a %wildcard_to_arg() function (for the example menu entry above this would be 'mymodule_abc_to_arg()'). The _to_arg() function is invoked to retrieve a value that is used in the path in place of the wildcard. A good example is user.module, which defines user_uid_optional_to_arg() (corresponding to the menu entry 'tracker/%user_uid_optional'). This function returns the user ID of the current user.

    The _to_arg() function will get called with three arguments:

    _load() and _to_arg() functions may seem similar at first glance, but they have different purposes and are called at different times. _load() functions are called when the menu system is collecting arguments to pass to the callback functions defined for the menu item. _to_arg() functions are called when the menu system is generating links to related paths, such as the tabs for a set of MENU_LOCAL_TASK items.

    Rendering Menu Items As Tabs

    You can also make groups of menu items to be rendered (by default) as tabs on a page. To do that, first create one menu item of type MENU_NORMAL_ITEM, with your chosen path, such as 'foo'. Then duplicate that menu item, using a subdirectory path, such as 'foo/tab1', and changing the type to MENU_DEFAULT_LOCAL_TASK to make it the default tab for the group. Then add the additional tab items, with paths such as "foo/tab2" etc., with type MENU_LOCAL_TASK. Example:

    // Make "Foo settings" appear on the admin Config page
    $items['admin/config/system/foo'] = array(
      'title' => 'Foo settings',
      'type' => MENU_NORMAL_ITEM,
    );
    
    // Make "Tab 1" the main tab on the "Foo settings" page
    $items['admin/config/system/foo/tab1'] = array(
      'title' => 'Tab 1',
      'type' => MENU_DEFAULT_LOCAL_TASK,
    );
    
    // Make an additional tab called "Tab 2" on "Foo settings"
    $items['admin/config/system/foo/tab2'] = array(
      'title' => 'Tab 2',
      'type' => MENU_LOCAL_TASK,
    );

    Return value

    An array of menu items. Each menu item has a key corresponding to the Drupal path being registered. The corresponding array value is an associative array that may contain the following key-value pairs:

    
          'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
        

    For a detailed usage example, see page_example.module. For comprehensive documentation on the menu system, see http://drupal.org/node/102338.

    Related topics

    63 functions implement hook_menu()

    File



    Code

    function hook_menu() {
      $items['example'] = array(
        'title' => 'Example Page',
        'page callback' => 'example_page',
        'access arguments' => array(
          'access content',
        ),
        'type' => MENU_SUGGESTED_ITEM,
      );
      $items['example/feed'] = array(
        'title' => 'Example RSS feed',
        'page callback' => 'example_feed',
        'access arguments' => array(
          'access content',
        ),
        'type' => MENU_CALLBACK,
      );
      return $items;
    }

    Comments

    roynilanjan’s picture

    According to https://api.drupal.org/comment/56808#comment-56808, though it works and drupal incorporate this access-control but conceptually seems not a good solution, because default access callback out-of-box handles the user_access and user_access have $account in signature which is a current login user, and every user assign to specific role/roles. So seems always better to use the permission attribute in the access arguments so we can manage the access-control-flow using the permission only & for that we do not need to use custom access callback.

    Note: Custom access callback is applicable if we need to control more granular level e.g. we want access control on top of $node so we need to handle node_access and on that context it's helpful to write some access callback with custom logic using user_access & node_access

    natuk’s picture

    In this unlikely scenario:

    then visiting example-name/example-name/test will give you a "page not found" message. The two names cannot be the same.

    kiamlaluno’s picture

    A module machine name (or module short name) can only contains the characters that are allowed in a PHP function name. You cannot use example-name as module machine name, since you cannot have a function whose name starts with example-name, which also means you cannot even implement hooks for that module.

    avinash_thombre’s picture

    Good if we include the callback function in the code and write some valid code, this will not let complete white screen and ascertain the code written is working. e.g.-

    function custom_example_menu() {
    $items = array();

    $items['admin/config/system/custom-example'] = array(
    'title' => 'Custom Example',
    'page callback' => 'customexample_page',
    'access callback' => TRUE,
    );

    return $items;
    }
    /*
    * include following call back page
    */
    function customexample_page() {
    return 'Hi, this custom example config page and code is working!';
    }

    • you have a sub-site installation with the sub-directory name "example-name"

    • you have a custom module with the same name (i.e. "example-name")

    • you define this

      $items['example-name/test'] = array(
          'page callback' => 'drupal_get_form',
          'page arguments' => array('example-name_test'),
        );
      
    • modules/

      system/

      system.api.php, line 1264

    • Hooks provided by Drupal core and the System module.

    • Hooks

    • Allow modules to interact with the Drupal core.

    • MENU_NORMAL_ITEM: Normal menu items show up in the menu tree and can be moved/hidden by the administrator.

    • MENU_CALLBACK: Callbacks simply register a path so that the correct information is generated when the path is accessed.

    • MENU_SUGGESTED_ITEM: Modules may "suggest" menu items that the administrator may enable.

    • MENU_LOCAL_ACTION: Local actions are menu items that describe actions on the parent item such as adding a new user or block, and are rendered in the action-links list in your theme.

    • MENU_LOCAL_TASK: Local tasks are menu items that describe different displays of data, and are generally rendered as tabs.

    • MENU_DEFAULT_LOCAL_TASK: Every set of local tasks should provide one "default" task, which should display the same page as the parent item.

    • "tab_parent": For local task menu items, the path of the task's parent item; defaults to the same path without the last component (e.g., the default parent for 'admin/people/create' is 'admin/people').

    • "tab_root": For local task menu items, the path of the closest non-tab item; same default as "tab_parent".

    • "position": Position of the block ('left' or 'right') on the system administration page for this item.

    • "type": A bitmask of flags describing properties of the menu item. Many shortcut bitmasks are provided as constants in menu.inc:


      If the "type" element is omitted, MENU_NORMAL_ITEM is assumed.

    • "options": An array of options to be passed to l() when generating a link from this menu item. Note that the "options" parameter has no effect on MENU_LOCAL_TASKMENU_DEFAULT_LOCAL_TASK, and MENU_LOCAL_ACTION items.

    • MENU_CONTEXT_PAGE: (default) The tab is displayed as local task for the page context only.

    • MENU_CONTEXT_INLINE: The tab is displayed as contextual link outside of the primary page context only.

    • "title": Required. The untranslated title of the menu item.

    • "title callback": Function to generate the title; defaults to t(). If you require only the raw string to be output, set this to FALSE.

    • "title arguments": Arguments to send to t() or your custom callback, with path component substitution as described above.

    • "description": The untranslated description of the menu item.

    • "page callback": The function to call to display a web page when the user visits the path. If omitted, the parent menu item's callback will be used instead.

    • "page arguments": An array of arguments to pass to the page callback function, with path component substitution as described above.

    • "delivery callback": The function to call to package the result of the page callback function and send it to the browser. Defaults to drupal_deliver_html_page() unless a value is inherited from a parent menu item. Note that this function is called even if the access checks fail, so any custom delivery callback function should take that into account. See drupal_deliver_html_page() for an example.

    • "access callback": A function returning TRUE if the user has access rights to this menu item, and FALSE if not. It can also be a boolean constant instead of a function, and you can also use numeric values (will be cast to boolean). Defaults to user_access() unless a value is inherited from the parent menu item; only MENU_DEFAULT_LOCAL_TASK items can inherit access callbacks. To use the user_access() default callback, you must specify the permission to check as 'access arguments' (see below).

    • "access arguments": An array of arguments to pass to the access callback function, with path component substitution as described above. If the access callback is inherited (see above), the access arguments will be inherited with it, unless overridden in the child menu item.

    • "theme callback": (optional) A function returning the machine-readable name of the theme that will be used to render the page. If not provided, the value will be inherited from a parent menu item. If there is no theme callback, or if the function does not return the name of a current active theme on the site, the theme for this page will be determined by either hook_custom_theme() or the default theme instead. As a general rule, the use of theme callback functions should be limited to pages whose functionality is very closely tied to a particular theme, since they can only be overridden by modules which specifically target those pages in hook_menu_alter(). Modules implementing more generic theme switching functionality (for example, a module which allows the theme to be set dynamically based on the current user's role) should usehook_custom_theme() instead.

    • "theme arguments": An array of arguments to pass to the theme callback function, with path component substitution as described above.

    • "file": A file that will be included before the page callback is called; this allows page callback functions to be in separate files. The file should be relative to the implementing module's directory unless otherwise specified by the "file path" option. Does not apply to other callbacks (only page callback).

    • "file path": The path to the directory containing the file specified in "file". This defaults to the path to the module implementing the hook.

    • "load arguments": An array of arguments to be passed to each of the wildcard object loaders in the path, after the path argument itself. For example, if a module registers path node/%node/revisions/%/view with load arguments set to array(3), the '%node' in the path indicates that the loader function node_load() will be called with the second path component as the first argument. The 3 in the load arguments indicates that the fourth path component will also be passed to node_load() (numbering of path components starts at zero). So, if path node/12/revisions/29/view is requested, node_load(12, 29) will be called. There are also two "magic" values that can be used in load arguments. "%index" indicates the index of the wildcard path component. "%map" indicates the path components as an array. For example, if a module registers for several paths of the form 'user/%user_category/edit/*', all of them can use the same load function user_category_load(), by setting the load arguments to array('%map', '%index'). For instance, if the user is editing category 'foo' by requesting path 'user/32/edit/foo', the load function user_category_load() will be called with 32 as its first argument, the array ('user', 32, 'edit', 'foo') as the map argument, and 1 as the index argument (because %user_category is the second path component and numbering starts at zero). user_category_load() can then use these values to extract the information that 'foo' is the category being requested.

    • "weight": An integer that determines the relative position of items in the menu; higher-weighted items sink. Defaults to 0. Menu items with the same weight are ordered alphabetically.

    • "menu_name": Optional. Set this to a custom menu if you don't want your item to be placed in Navigation.

    • "expanded": Optional. If set to TRUE, and if a menu link is provided for this menu item (as a result of other properties), then the menu link is always expanded, equivalent to its 'always expanded' checkbox being set in the UI.

    • "context": (optional) Defines the context a tab may appear in. By default, all tabs are only displayed as local tasks when being rendered in a page context. All tabs that should be accessible as contextual links in page region containers outside of the parent menu item's primary page context should be registered using one of the following contexts:


      Contexts can be combined. For example, to display a tab both on a page and inline, a menu router item may specify:

    • $arg: A string representing whatever argument may have been supplied by the caller (this is particularly useful if you want the _to_arg() function only supply a (default) value if no other value is specified, as in the case of user_uid_optional_to_arg().

    • $map: An array of all path fragments (e.g. array('node','123','edit') for 'node/123/edit').

    • $index: An integer indicating which element of $map corresponds to $arg.




普通分类: