6.x core.php hook_menu_alter(&$items)
7.x system.api.php hook_menu_alter(&$items)

Alter the data being saved to the {menu_router} table after hook_menu is invoked.

This hook is invoked by menu_router_build(). The menu definitions are passed in by reference. Each element of the $items array is one item returned by a module from hook_menu. Additional items may be added, or existing items altered.


$items: Associative array of menu router definitions returned from hook_menu().

Related topics

1 function implements hook_menu_alter()

Note: this list is generated by pattern matching, so it may include some functions that are not actually implementations of this hook.

comment_menu_alter in modules/comment/comment.module
Implements hook_menu_alter().
1 invocation of hook_menu_alter()
menu_router_build in includes/menu.inc
Collects and alters the menu definitions.


modules/system/system.api.php, line 1292
Hooks provided by Drupal core and the System module.


function hook_menu_alter(&$items) {

  // Example - disable the page at node/add
  $items['node/add']['access callback'] = FALSE;


gisle’s picture

The following implements hook_menu_alter to remove access to the "forum" tab for the anonymous user:

 * Implements hook_menu_alter.
 * Check access for forum menu item.
function MYMODULE_menu_alter(&$items) {
  $items['forum']['access callback'] = '_accesscheck';

 * Callback to disallow access for the anonymous user.
function _accesscheck(){
  global $user;
  return $user->uid;

If you do not grant the anomymous user access to forum content, the anomymous user still has access to the forum landing page. This is rather pointless, so the example above is useful if you want to avoid this.

mhazy’s picture

A lot of projects we do require hiding the standard "/node" page (you can change the front page, but /node stays active)

 * Restrict access to /node
function MODULE_menu_alter(&$items) {
    $items['node']['access callback'] = FALSE;
Marko B’s picture

This one makes you a redirect loop.

Charles Belov’s picture

function mymodule_menu_alter(&$items) {
pit1988’s picture

please how to modify the title of an admin item for logged users ? (admin see item : all users, but user 1 see : my profile)

gusantor’s picture

hello, any clue about how to get this to work for node/%node/workflow menu ?

I'm using workflow fields

for testing, I've implemented

function my_module_menu_alter(&$items){
$items['node/%node/workflow']['access callback'] = '_my_function';

function _my_function(){
return true;

but this doesn't work, the menu just disappear, even when I return true in _my_function


TarKHaoS’s picture

Try replacing replace "%node" by "%":

$items['node/%/workflow']['access callback'] = '_my_function';

I had a similar issue, I think that should be documented here.

gusantor’s picture

thank you ! , I'm not over this by now

I hope soon do some tests and post results results

avinash_thombre’s picture

Just to test this hook (for beginners) use following example.

function custom_example_menu_alter(&$items){
// This will change 'node/add/page' title to 'Add new page' i.e. it would be changed from "Basic Page" to "Add new page".
$items ['node/add/page']['title'] = 'Add new page';
$items['node/add/page']['description'] = t('New text description for hook_alter_menu.');

Once you write this hook and save, do not forget to clear menu cache and you can check the changes reflected at 'site_/node/add'.

develop2015deepak’s picture

I have to restrict group admin to remove other admin in Oraganic group and i am using hook_menu_alter to change the $items['group/%/%/admin/people/delete-membership/%og_membership']['access callback'] = '_access_callback_menu_alter'; . The menu is defined in og_ui.module . Now i am getting access denied for all the users after simply return true value . Give suggestions Please i am now stuck with this because i have altered other menus also and it is working fine but not this is ..

ItangSanjana’s picture

Most of the time you need to implement hook_module_implements_alter too.

function YOURHOOK_menu_alter(&$items) {
  $items['THE/PATH']['access callback'] = _YOURFUNCTION;

function _YOURFUNCTION() {
  return YOURLOGIC;

function YOURHOOK_module_implements_alter(&$implementations, $hook) {
  if (in_array($hook, array('menu_alter')) && isset($implementations['YOURHOOK'])) {
    $group = $implementations['YOURHOOK'];
    $implementations['YOURHOOK'] = $group;