I have created a small module (which I'll call "mymodule" here, names changed to protect the innocent) which shows a custom page. In this simplified example of what I'm attempting to accomplish, once the module is installed and enabled, a new "My Module Page" link shows up on the Navigation menu, and when it's clicked, a page is displayed with some dynamically-generated content, with "My Module Page" as the page header. But in the settings of my module, I allow the site admin to change the title of this page. How? Here is the hook_menu code for my module:
function mymodule_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'path' => 'mymodule',
'title' => variable_get('mymodule_title_of_page', t('My Module Page')),
'access' => user_access('access content'),
'callback' => 'show_mymodule_page'
);
$items[] = array(
'path' => 'admin/settings/mymodule',
'title' => t('My Module Settings'),
'description' => t('Settings for My Module.'),
'callback' => 'drupal_get_form',
'callback arguments' => array('mymodule_admin_settings'),
'access' => user_access('administer site configuration'),
'type' => MENU_NORMAL_ITEM
);
}
return $items;
}
As you can see from the line 'title' => variable_get('mymodule_title_of_page', t('My Module Page')), the menu entry for the item is dynamically named based on what the user entered on the Settings page (which, obviously, has a text field for "mymodule_title_of_page"). The problem is that when the user changes the value for this setting, it is not reflected in the menu or the title of the page because the cache_menu table still has the old name in it. I know the following code is supposed to clear the cache:
cache_clear_all(NULL, 'cache_menu');
But I have two problems I can't seem to solve:
- The function doesn't work, and the cache is NOT cleared unless I do it manually
- Assuming I get the function to work, how do I invoke it every time the settings are changed?
I guess I can invoke the cache-clearing when displaying the settings form, by adding it to the mymodule_form() function. That might solve the problem anyway, since it re-displays after submitting. But as a purist, I want it to invoke upon submission, via some kind of hook that simply invokes the code whenever the settings change. I can't find any such hook. Is there a way?
P.S.: I have also considered using drupal_set_title to simply set the title of the page to the new variable upon displaying the module page. But I can still see instances where using a Settings page to change a menu item's title and page title could be useful. So any insight would be appreciated!!!
Comments
Invite Module
Not sure if you're still trying to figure this out, but I would recommend checking out the Invite module. They do something very similar.
Same problem...
attempting to figure out a way around this as well. any help would be great.
at least part of it
Seems like the proper way to clear menu_cache:
cache_clear_all('*', 'cache_menu', TRUE);
use 'title callback' option
In D6 there's a new option for a menu item called 'title callback'. This function is by default set to 't()' to allow localization, but can be set to a user-defined function to allow any modification on the title string.
3 ways
There's a number of ways you can do this:
1. you can use menu_rebuild();
2. You can modify your code so that the dynamic menu item is not cached. Moving it in this way causes it to be added to the tree when $may_cache = FALSE:
3. Use drupal_set_title($title); in your callback function to modify the page title without affecting the menu tree.
I'm not certain of this but I believe option 3 would be the most resource efficient.
Drupal 6+
Thank you GeoffBrown for your post.
I test your 3 methods in Drupal 6 and it's a bit different to old versions of Drupal I guess...
1. menu_rebuild() is working fine, but it's quite intensive. I try to use the minimum requirement on that function to reset the menu and it seems that those 2 lines are good enough:
but it's not really faster.
2. $may_cache: According to the documentation, this is not any more valid in new version of Drupal (6+).
http://api.drupal.org/api/function/hook_menu
3. drupal_set_title($title); is not resetting the whole menu. I'm not sure what it does, but that's not enough.
Thanks for your post,
Thanks for your post, gaellafond. It turns out that
menu_router_build(TRUE);is needed if you have changed router items and I was missing that!