I'm trying to have my module have it's own custom menu. Before I was trying to manually enter it into the database, but it didn't work (although I have no idea why). But it seems the better solution is to just use a "menu_name" attribute in the hook_menu function. However it doesn't seem to work when I do it.

<?php
	$items['mymodule/settings'] = array( 					
		'title'=>'Daedalus Settings',
		'description'=>t("Administrator settings to the module"),
		'page callback' => 'mymodule_settings_page',
		'access arguments' =>array('access content'),
		'type' => MENU_NORMAL_ITEM,	
		"menu_name" => 'mymodule',		
	);


?>

However when I do that, there is no mymodule menu. It doesn't even work if I create a menu, and call it mymodule. (I have cleared the cache for each attempt).

Is there something I'm clearly doing wrong?

Comments

jaypan’s picture

You need to prefix the menu name with menu-

The documentation isn't clear on that. Took me forever to figure it out myself. I think I made a comment on the API page, but maybe not.

Contact me to contract me for D7 -> D10/11 migrations.

Matt I’s picture

thank you very much.

Where do I find then menu though? When I go to list menus, it doens't show up, but if I try to create one with the same name, it says it already exists.

jaypan’s picture

What?

Contact me to contract me for D7 -> D10/11 migrations.

Matt I’s picture

I added the -menu prefix.

But when I go to /admin/build/menu/list, the mymodule menu isn't there.

When I go to create the menu (thinking maybe it only shows up once you create it), it says it can't be created because the menu already exists. So that means that the "menu_name" is creating the menu. I just have no idea where to find the menu, and enable it.

jaypan’s picture

You said 'prefix', but you showed a suffix. And the suffix wasn't even the same code I showed you.

Contact me to contract me for D7 -> D10/11 migrations.

Matt I’s picture

I meant prefix, sorry. This is what I now have

<?php
	$items['mymodule/settings'] = array( 									
		'title'=>'Settings',
		'description'=>t("Administrator settings to the module"),
		'page callback' => mymodule_settings_page',
		//'page arguments' => array('mymodule_admin_settings'),
		'access arguments' =>array('access content'),
		'type' => MENU_NORMAL_ITEM,	
		"menu_name" => 'menu-mymodule',		
	);
?>
jaypan’s picture

Why don't you show us your actual code?

Edit: And did you clear your cache after making the change?

Contact me to contract me for D7 -> D10/11 migrations.

Matt I’s picture

Well, it's pretty much identical. I was just changing the module name to mymodule, to try and keep it more generic. It would be more useful for future googlers.

<?php
	$items['daedalus/settings'] = array(
		'title'=>'Daedalus Settings',
		'description'=>t("Administrator settings to the daedalus module"),
		'page callback' => 'daedalus_settings_page',
		//'page arguments' => array('daedalus_admin_settings'),
		'access arguments' =>array('access content'),
		'type' => MENU_NORMAL_ITEM,	
		"menu_name" => 'menu-daedalus',		
	);

?>

and I did clear the cache. I didn't see anything in the menu_custom table for it either

jaypan’s picture

Are you sure that your menu name is daedalus?

Look at the HTML for the menu. The menu_name should either be the same as the ID for the menu, or have menu- prefixed to it (I can't remember which off the top of my head).

Contact me to contract me for D7 -> D10/11 migrations.

Matt I’s picture

the menu doesn't actually exist anywhere. It's not in the html or anything anyway. And daedalus doesn't show up anywhere, and the menu doesn't exist in custom_menu table.

So where should I look exactly?

and I'm 100% positive the module name is daedalus

jaypan’s picture

I mean the actual menu, not the item you are trying to add to the menu. Look at the ID for the rest of the menu.

You will have created a menu through the interface, then added it to a block in your site. The other menu items in that menu will appear in that block. Look at the ID for the menu.

Contact me to contract me for D7 -> D10/11 migrations.

Matt I’s picture

All I'm finding in the source is

< div class='content'>

jaypan’s picture

Look at the ID of the parent <div> of the <div class="content">. Paste it here.

Contact me to contract me for D7 -> D10/11 migrations.

Matt I’s picture

<div id="block-user-1" class="clear-block block block-user">

above that is

<div id="sidebar-left" clalss="sidebar">

jaypan’s picture

You are looking at the wrong HTML.

Have you actually added any other links to the menu in question, and have you added the menu as a block to somewhere on your page?

Contact me to contract me for D7 -> D10/11 migrations.

Matt I’s picture

I'm trying to have the links populate a custom menu. But I want my module to create the menu. Maybe there's something I didn't do properly.

I didn't create a menu with the interface. Basically what I'm trying to do (maybe you have a better idea of what I should be doing).

My module creates a table dae_settings. In the settings table, it holds some strings, which are the url's to different forms. And I want those url's to dynamically added to a menu, which exists because module made it.

If someone were to install my module, there should be a new menu, "daedalus-menu". And I want that menu dynamically populated with urls from the settings table. (the dynamic part is important, because they are changable)

But as of now, once I made link, I havn't added any blocks or anything. There aern't any that I can add. Nothing shows up in the list of blocks, nothing shows up in the list of menu list. I've even tried manually adding information to the menu tables, but nothing seems to have worked.

jaypan’s picture

Ok, now I'm getting it.

You are misunderstanding what hook_menu() does. The name is actually misleading. It doesn't actually create menus. Rather, hook_menu() maps (connects) a path to a function. It will also add the newly created link to a menu if you want it to (and does this by default), but the primary purpose of hook_menu() is not to do this, but just to create a link.

So using hook_menu, I can tell Drupal that when the path 'mypath' is accessed, I want it to execute the function 'myfunction'. Now when someone goes to mysite.com/mypath, the system will execute myfunction(). By default, Drupal will also add the newly created link to the navigation menu, which is the Drupal default menu. However, if I wish, I can tell it to add that link to another menu that already exists on the site. Now notice the use of the word menu here - these are not menu items, rather a menu is a collection of links.

You are trying to add your menu item to a menu that doesn't exist yet. So it doesn't work. For this to work, you have to have created the menu already. The menu itself doesn't actually have to be displayed on the site anywhere for this to work, but if the menu hasn't been created, then the link cannot be added to it.

To do what you want to do, you would need to do the following:
1) Programmatically create a menu BEFORE executing hook_menu() (most likely in hook_install() though maybe you would prefer to do it some other way).
2) Use that menu name in your 'menu_name' element of your hook_menu() declaration.
And optionally:
3) Programmatically add the menu to one of the regions of the template (if you don't do this, the menu won't display anywhere until the user goes to administer -> site building -> blocks)

Contact me to contract me for D7 -> D10/11 migrations.

Matt I’s picture

Ok, awesome. It's working now.

thank you very much :)

bojanz’s picture

Paste the whole hook please, not just what's in it.

Matt I’s picture

<?php

//implementation of hook_menu
function daedalus_menu () {//menu_link_save(&$item)

/*******FIX*********
		menu items to all prepend with daedalus.
		also change code so that 100% of functions begin with daedalus.*/
	$items = array();
	
/*******FIX*********/
	//a page for the module settings. Eventually move to the content
	$items['daedalus/settings'] = array( 									//this page has a finate location that will not be changed.
		'title'=>'Daedalus Settings',
		'description'=>t("Administrator settings to the daedalus module"),
		'page callback' => 'daedalus_settings_page',
		//'page arguments' => array('daedalus_admin_settings'),
		'access arguments' =>array('access content'),
		'type' => MENU_NORMAL_ITEM,	
		"menu_name" => 'menu-daedalus',		
	);

/*******FIX*********/	
	//a page for submitting a course
	//get the url from db
	$items[daedalus_get_setting("submit course url")] = array(									//URL is dynamically retrieved from module settings table
		'title' 			=> 'Submit a new course',
		'page callback' 	=> 'course_page', //defined function
		'access arguments'	=>	array('access content'),
		'type'				=>	MENU_NORMAL_ITEM,
		"menu_name" => 'menu-daedalus',
	);
/*******FIX*********/	
	//a page to submit course codes that will be considered valid
	$items[daedalus_get_setting("submit valid course code url")] = array(
		'title'				=>	"Submit a new valid course code",		//STATUS: COMPLETE
		'page callback'		=>	'daedalus_codes_page',
		'access arguments'	=>	array('access content'),
		'type'				=> 	MENU_NORMAL_ITEM,
		"menu_name" => 'menu-daedalus',
	);
/*******FIX*********/	
	$items[daedalus_get_setting("submit slo url")] = array(
		'title'				=>	"Submit a new SLO",						//STATUS: COMPLETE
		'page callback'		=>	'slo_page',
		'access arguments'	=>	array('access content'),
		'type'				=>	MENU_NORMAL_ITEM,
		"menu_name" => 'menu-daedalus',
	);
/*******FIX*********/
	//a page to compleatly edit a course	
	$setting = "edit course url";
	$result = db_query("select * from {dae_settings} where setting='%s'",$setting);
	$row = db_fetch_array($result);
	$url = $row['value'];
	
	$items[daedalus_get_setting("edit course url")] = array(								//STATUS: INCOMPLETE, IMPORTANT
		'page callback'	=>	'course_edit_page',
		'access arguments'	=> array('access content'),
		'type'	=> MENU_NORMAL_ITEM,
		"menu_name" => 'menu-daedalus',
	);
/*******FIX*********/	
	//a page to compleatly edit an slo	
	$items[daedalus_get_setting("edit slo url")] = array(
		'page callback' => 'slo_edit_page',
		'access arguments' => array('access content'),
		'type' => MENU_NORMAL_ITEM,
		
	);
		
/*******FIX*********/	
	//some pages for autocomplete functions to live
	$items['autocomp/coursecode'] = array(
		'title' => 'Autocomplete',
		'page callback'	=> 'coursecode',
		'access arguments' => array('access content'),
		'type' => MENU_SUGGESTED_ITEM,
	);
/*******FIX*********/	
	$items['autocomp/course'] = array(
		'title'	=>	'Autocomplete',
		'page callback' => 'course',
		'access arguments' => array('access content'),
		'type' => MENU_SUGGESTED_ITEM,
	);
/*******FIX*********/	
	$items['autocomp/slo'] = array(
		'title'=>'Autocomplete',
		'page callback' => 'slo',
		'access arguments' => array('access content'),
		'type' => MENU_SUGGESTED_ITEM,
	);
	
	return $items;
}?>
jorje29’s picture

A BIG thank you to Jay Matwichuk for the phrase " You need to prefix the menu name with menu- .The documentation isn't clear on that. Took me forever to figure it out myself. "

I really doubt I could figure it out by myself, GREAT TIP...

darrellduane’s picture

In Drupal 7, I found that you do not need to prefix the menu name with 'menu-'. It works when I use the menu name (as displayed in the URL when editing the Menu). For example:

 $items['bulk_upload'] = array(
    'title' => 'Bulk Upload Files',
    'description' => 'Upload files that have a status of Ready for Bulk Upload',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('memepod_bulk_upload_form'),
    'access arguments' => array('administer'),
    'menu_name'          => 'main-menu',
    'type' => MENU_NORMAL_ITEM,
  );

Darrell Duane
d@duane.com

onehandsomedog’s picture

Thanks! Very helpful. Sometimes I'm amazed what an extra 1 or 2 flushing caches will do

greendwarf’s picture

I was able to get my custom module links working correctly after reading this discussion. Thanks everyone!

Gik000’s picture

Anyway you can not create a menu link with a parameter like % in your path.
I suggest to manage it with an alias and a drupal_goto with your parameters gotten in other ways.

kingandy’s picture

This is a five year old Drupal 6 issue ... and nobody has mentioned %. But you totally can use % as a wildcard in Drupal 6/7 hook_menu paths. It's a pretty standard way of passing parameters into your callbacks.

++Andy

jaypan’s picture

You can create menu items with wildcards, but you cannot add those items to menus, which is what the previous poster was saying.

Contact me to contract me for D7 -> D10/11 migrations.