how can I make my menu items accept query parameters? i.e. I would like to create a menu item such as node/add/story?destination=someotherplace but creating this as a menu just encodes the ?.

Would the following code be advisable?

function mycustomtheme_menu_item_link($item, $link_item) {
  if(!isset($item['query'])) {
    $path = explode('?', $link_item['path']);
    $link_item['path'] = $path[0];
    $item['query'] = $path[1];
  }
  return l($item['title'], $link_item['path'], !empty($item['description']) ? array('title' => $item['description']) : array(), isset($item['query']) ? $item['query'] : NULL);
}

Comments

mikeschinkel’s picture

Generally I hate it when I post a question on a forum and rather than get an answer someone asks me why I want to do it that way so please forgive me in advance when I ask why you want to do it that way instead of as node/add/story/destinations/someotherplace, or similar?

(I would answer you but I don't know the answer without testing it first...)

panis’s picture

because the destination query argument is used by drupal to redirect the user to a specific location "someotherplace" after the form is submitted.

providing it in the manner above (node/add/story/destinations/someotherplace) which if it worked would have been great - but will not make drupal redirect to someotherplace after adding the story on the otherhand: node/add/story?destination=someotherplace will redirect.

lapricorn’s picture

i am having the same problem. did you find a solution for that?

panis’s picture

had no luck with the boards here -- so after some digging into the menu code you can override the menu_item_link theme to do this.

in your template.php for your theme.

function phptemplate_menu_item_link($item, $link_item) {
  if(!isset($item['query'])) {
    $path = explode('?', $link_item['path']);
    $link_item['path'] = $path[0];
    $item['query'] = $path[1];
  }
  return l($item['title'], $link_item['path'], !empty($item['description']) ? array('title' => $item['description']) : array(), isset($item['query']) ? $item['query'] : NULL, NULL, NULL, TRUE);
}
lapricorn’s picture

thanks a lot for your help. it works fine.

dugh’s picture

Thanks very much for sharing that.
I'm using the members module to display lists of people by role, and it sorts by default based on the leftmost column, which in my case is a picture. So I needed to add that query string to the path to link people to the list sorted by last name.

scottrigby’s picture

Hi Panis,
Is there a way to add the current url as the destination to a menu link?

I ask because - like others - I have added a 'Log in' link to my menu.

What I'd like is to add the current url as the destination (wherever the user is when she happens to click the Log in link).

Here is a menu-like-link I made in a custom block (I added thsi block below the Navigation block, then used CSS to make this appear as if the link were the last menu-item in the navigation menu):

<?php
          $current_path = $_REQUEST['q'];
          global $user;
          if ($user->uid) {
            $thetext = "Log out " . $user->name;
            $thepath = "logout";
          } else {
            $thetext = "Log in";
            $thepath = "user/login";
          }  
?>
<ul class="menu">
<li class="leaf last"><a href="<?php print base_path() . $thepath . '?destination='. $current_path; ?>"><?php print $thetext ?></a></li>
</ul>

Ideally however, I could just use a theme override to add this dynamic ?destination to the end of the login link, as a menu item (so it can be rearranged within the menu, etc).

Any advice would be very appreciated - thanks in advance :)
Scott

scottrigby’s picture

After a lot of looking, I finally found something that works.

In my theme's template.php (I'm using a zen subtheme), I override zen's theme_menu_item_link() function.

Added this line (adapted from Drupal 6 core api):

  // add destination for login link
  if ($link['href'] == 'user/login') {
    $link['localized_options']['query'] = drupal_get_destination();
  }

All you need to do at that point is create a menu item pointing to 'user/login', and this function will add the destination to the end.

So the entire function (again, for a zen subtheme) looks like this:

/**
 * Implements theme_menu_item_link()
 */
function MYZENSUBTHEMENAME_menu_item_link($link) {
  if (empty($link['localized_options'])) {
    $link['localized_options'] = array();
  }
  
  // add destination for login link
  if ($link['href'] == 'user/login') {
    $link['localized_options']['query'] = drupal_get_destination();
  }

  // If an item is a LOCAL TASK, render it as a tab
  if ($link['type'] & MENU_IS_LOCAL_TASK) {
    $link['title'] = '<span class="tab">' . check_plain($link['title']) . '</span>';
    $link['localized_options']['html'] = TRUE;
  }

  return l($link['title'], $link['href'], $link['localized_options']);
}

Scott Rigby
http://basekamp.com
http://PlausibleArtworlds.org

seansies’s picture

Hey Scott, I'm looking for help on menu_item_link.

I'm using ThemeKey to change the theme on a series of pages on my website that have a completely different theme from the rest of the site -- based on a parameter appended to the url. Some of these pages are nodes that must be able to be updated from the subtheme side, as well as the main theme. So I’m trying to hook into the menu_item_link in template.php, but it doesn’t like my code. I copied the applicable snippet from the zen theme template php, and modified it as below for my zen_dis sub theme -- It still seems to be looking at the main Zen theme for this option, though – how do I phrase the Hook_ language to force it to use this?:

function zen_dis_menu_item_link($link) {
if (empty($link['localized_options'])) {
$link['localized_options'] = array();
}

// If an item is a LOCAL TASK, render it as a tab
if ($link['type'] & MENU_IS_LOCAL_TASK) {
$link['title'] = '' . check_plain($link['title']) . '';
$link['localized_options']['query'] = '?dis-site-search-organization';
$link['localized_options']['html'] = TRUE;
}

return l($link['title'], $link['href'], $link['localized_options']);
}

Matthew Davidson’s picture

From what I can see, if you want to redirect from a node editing form, the best way to do it is to use hook_form_alter() on the node editing form to add a #redirect value. e.g.:

function YOURMODULE_form_alter($form_id,&$form) {
  switch ($form['#id']) {
    case 'node-form':
       if ($form['type']['#value'] == 'story') {
         $form['#redirect'] = 'some/other/place';
       }
     break;
  }
}
panis’s picture

using the menu approach makes it easy to create redirects without having to write or modify code when the destination path changes or if I have multiple paths each of which need to get to a different place. So I think this is a better approach for what I am trying to accomplish.

Also I do not see why the menu module should not jump to the exact link that I provide the link path with.. i.e. why it htmlencodes the path I provide it.

garethsprice’s picture

For anyone creating menu links programatically, through hook_menu_link_alter or similar, we can provide an array of key/value pairs under $item['localized_options']['query'] to add query attributes to the URL.

eg:
$item['href'] = 'node/add/page';
$item['localized_options']['attributes']['class'] = 'error';
$item['localized_options']['query'] = array('edit[title]'=>$item['title']);

msankhala’s picture

Here is existing issue. Have a patch which should solve query parameter encoding issue.
https://www.drupal.org/node/1220410

खम्मा घणी
Mahesh Sankhala
Tech Architect

cdonner’s picture

I repeatedly ended up on this page while searching for a Drupal 7 solution that does not require absolute URLs (unsuccessfully). I am going to leave this comment here, should I ever end up here again myself, or anybody else who ran into this issue.

After playing with tokens a bit, I figured out that the query string is accepted when prefixing the Drupal URL with this token (after enabling tokens, of course):

[site:url]

For some reason I had to save the menu item twice. After saving it only once, the link would be something like this:

http://[mysite]/menutoken/5b95c1ff42d7a

After saving it a second time, the link became the correct URL full with the query string.

dru pal’s picture

This was awesome! It worked! Thanks!