Creating Custom Menus in Drupal

Drupal has a very customizable architecture so that you can extend Drupal to suit your needs.

Drupal provides various kinds of hooks which a module can use to customize the functionality, and has a powerful menu system to create menu items in your Drupal site.

Drupal also provides hooks for module developers to hook into the Drupal menu system and create menu items for the module to function. The menu system hooks in Drupal allow registering of URLs so that the module can define how the request to the URL will be handled and also if the module wants to add that link to the menu.

In this article we are going to see how your module can hook into the Drupal menu system to register callbacks on URLs and how to add those in the navigation menu if needed.

Creating the module

Let’s start by creating a separate module called menudemo which we will use to demonstrate the various menu system functionalities that Drupal offers us.

To create the menudemo module create a folder in menudemo sitesallmodulescustom  of your Drupal installation. In that folder create a file called menudemo.info with the following contents.

;$Id$
name = menudemo
description = A module to  demo drupals menu system
package = Menu Demo Package
core = 7.x
files[] = menudemo.module

The menudemo.info file describes our module to the Drupal system. In the info file we have described various parameters such as the name of the module, the description, the package name etc.

Also in your menudemo folder create your menudemo.module file.

Your folder structure will be as follows:

menu structure

Once you have added your files, you should be able to see your module in the Drupal module list. You should go and enable the module now as shown below.

menu module

Responding to a URL via menu callback

Once we have created our module with the necessary files, let’s look at the hook Drupal provides to module developers as a way to hook into the Drupal menu system.

For a module to hook into the Drupal menu system, one has to implement the hook_menu hook. This implementation of this hook is required to return an associative array of the menu items the module is suppose to add. The associative array will contain the paths of the menu as the key and its properties as the value of that array item.

So, in our module we give the implementation of hook_menu by providing the function menudemo_menu as follows

/**

* Implementation of hook_menu().

*/

function menudemo_menu() {

    $menuitems['menudemo'] = array(

    'title' => 'My Menu',

    'page callback' => 'menudemo_mymenu_page_callback',

    'access callback' => TRUE,

    'type' => MENU_CALLBACK,

    );

    return $menuitems;

}

function menudemo_mymenu_page_callback() {

    return 'My Menu URL was hit';

}

In the function menudemo_menu above we have created an associative array with the key as menudemo which is the name of our module. But you can use a key here based on the URL you want to handle and respond to in your module.

Then we have passed the parameters defining the menu items such as its title. Defining the type as MENU_CALLBACK just means register a path which, when requested, will be able to handle the request. No new menu item will be created.

And we have also defined the access callback and set it as TRUE so that this menu item can be accessed by everyone.

We have defined the page callback in which you specify the function which should be called when this URL is accessed. We have defined it to menudemo_mymenu_page_callback. In the function menudemo_mymenu_page_callback we have just returned a string which we will display when our registered URL is requested.

Now just go to the URL <your drupal installation URL>/menudemo, if you have clean URLs enabled, or to <your drupal installation URL>/?q=menudemo if clean URLs are not enabled. You should be able to see the output of your page callback on the screen as follows

Note: – Drupal caches the hooks which a module implements so you might have to go to Administration » Configuration » Development » Performance and do a clear cache to take into consideration the new changes in the hooks implemented by your module in Drupal 7.

my menu 

Fetching the parameters from the menu URL

Drupal also lets you fetch parameters from the Drupal URL by passing it to your callback function.

So, if you have registered for a URL path and there are values after it in the URL then those are passed as parameters to your callback function. This becomes very handy when you want the menu item to work differently based on the parameter passed to it.

If, for instance, you wanted to add a menu item to process products on your site, you might have the same callback function cater to the different URL such as menudemo/product/add or menudemo/product/view etc. To catch the parameters we will have to modify our callback as shown below

function menudemo_mymenu_page_callback($firstparameter = '', $secondparameter ='') {
    $result = 'My Menu URL was hit';
    $result.='<br> The first parameter passed to the url is :'.$firstparameter;
    $result.='<br> The second parameter passed to the url is :'.$secondparameter;
    return $result;
}

Here there are two parameters caught and passed to the callback function. Then in the callback function we are just displaying the parameters on the screen. So in case if you to the URL <your drupal installation URL>/menudemo/product/edit the output will be as follows

your menu

Adding your menu links in the navigation bar

Up to now, we have seen how we can register URLs with the Drupal system so that any request to those URLs will be handled by our callback function.

If we want that URL to show up in the navigation menu, we can do that by changing the type of the menu item. The modified menudemo_menu function is as follows

/**

* Implementation of hook_menu().

*/

function menudemo_menu() {

    $menuitems['menudemo'] = array(

    'title' => 'My Menu',

    'page callback' => 'menudemo_mymenu_page_callback',

    'access callback' => TRUE,

    'type' => MENU_NORMAL_ITEM,

    );

    return $menuitems;

}

In the above function we have passed the type as MENU_NORMAL_ITEM. This will make the menu item show up in the navigation menu as shown below.

my menu url

Creating sub menu in the navigation bar

After you have created the item in the navigation menu, you might want to create submenus or nested menu items below it. We can add submenus to menu items by appending the submenu item path after the menu item path in the associative array we pass back in menudemo_menu function.

To add the sub menu we will update the function menudemo_menu as follows

/**

* Implementation of hook_menu().

*/

function menudemo_menu() {

    $menuitems['menudemo'] = array(

    'title' => 'My Menu',

    'page callback' => 'menudemo_mymenu_page_callback',

    'access callback' => TRUE,

    'type' => MENU_NORMAL_ITEM,

    );

    $menuitems['menudemo/submenu'] = array(

    'title' => 'My Sub menu',

    'page callback' => 'menudemo_mysubmenu_page_callback',

    'access callback' => TRUE,

    'type' => MENU_NORMAL_ITEM,

    );

    return $menuitems;

}

function menudemo_mysubmenu_page_callback() {

    $result = 'My  Sub Menu URL was hit';

    return $result;

}

Here we have added one more entry in the associative array with the key as menudemo/submenu. This will create a submenu below the menudemo menu item. We have defined the function menudemo_mysubmenu_page_callback as the callback function for the submenu item which just displays the text as 'My  Sub Menu URL was hit'.

Now if we click on the submenu item, we will be able to see the output as follows

my sub menu

Conclusion

The Drupal system lets the module developers plug into the Drupal main processing via Drupal hooks. In this article, we saw how we can use the hook_menu hook of the Drupal menu system to register our own callbacks to handle request to specific URLs or add menu items to the navigation menu.

The Drupal system also passes the parameters in the URL to the callback function, which can help to write a generic callback function that could handle multiple tasks based on the parameters passed to it.

Now, depending on the module you are trying to make in Drupal, you might want to add simple menu items or nested menu items to let the user easily access the functionality you are trying to provide.

Have fun adding menus to your next Drupal module.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Chuck Rodgers

    Going forward how does this fit in with patches and upgrades? Are there things to watch out for if you go down this path to keep things working on your site?

    • Abbas

      Hi ,
      The hook_menu in supported in Drupal 7 and in Drupal 8