Take the 2-minute tour ×
Drupal Answers is a question and answer site for Drupal developers and administrators. It's 100% free, no registration required.

In one of my forms, I'm trying to set a $form_state['redirect'] so the form will go to that destination after the user clicks one of the action buttons.

If I inspect $form_state['redirect'] both before and after I add the redirect, it is NULL before, and after contains the proper array. Here's how I'm setting up the redirect:

$form_state['redirect'] = array(
  'my/custom/path/' . $nid,
  array('query' => drupal_get_destination()),
);

I want to preserve the destination from the form that the user's viewing to the next path (that's why I'm calling drupal_get_destination(), which returns an array with 'destination' => 'some/path/here' inside.

It seems that, because there's already a destination in the path of the current form, the form redirects to that destination no matter what I put in my own form submit handler (see above code). I even tried using drupal_goto() and that didn't redirect the user either.

I could maybe rewrite $_REQUEST['destination'] explicitly, but that just seems unintuitive and un-Drupal-like to me. Plus it doesn't follow any conventions. (That didn't help - just tried it).

share|improve this question
3  
I think this is the third time in a year a Google search directed me back to my own question. –  geerlingguy Apr 12 '13 at 17:45

4 Answers 4

up vote 19 down vote accepted

When a form is processed, the value of $form_state['redirect'] is sent to drupal_goto(), and drupal_goto() always favors $_GET['destination'] over its own $path parameter.

For the sake of completeness, in Drupal 6, you were somewhat out of luck without setting your own headers in hook_exit():

function mymodule_exit($destination = NULL) {
  $my_destination = 'foo/bar';
  header('Location: ' . url($my_destination));
  exit;
}

In Drupal 7, hook_drupal_goto_alter() was added for this specific use case:

function mymodule_drupal_goto_alter(&$path, &$options, &$http_response_code) {
  $path = 'foo/bar';
}

Another option for Drupal 7, which is closer to what you want to do, is to reset the static cache for drupal_get_destination() in your submit handler using drupal_static_reset():

function mymodule_form_submit($form, &$form_state) {
  // See note
  $form_state['redirect'][] = drupal_get_destination();
  $form_state['redirect'][] = 'foo/bar';

  unset($_GET['destination']);
  drupal_static_reset('drupal_get_destination');
  drupal_get_destination();
}

Since you call drupal_get_destination() immediately after the reset, Drupal is blissfully unaware of the destination parameter for the rest of the page build, including when it calls drupal_goto().

Note: I changed the code for defining $form_state['redirect'] because you never want to overwrite the variable: other submit handlers might've defined their own redirects. Drupal will always use the last item in the array, so if you want foo/bar to override the destination parameter (and every other redirect defined up to that point), it needs to be last.

share|improve this answer
    
Perfect, and very good explanation. I actually found a little more by working through the flow of a processed form - drupal_goto() is ultimately the reason my simple 'redirect' wasn't working. I needed to overwrite $_GET['destination'] too. –  geerlingguy Jun 19 '11 at 23:46
    
Thanx! This is indeed very clarifying. –  zilverdistel Sep 27 '11 at 6:52

Great post had the exact problem given in the definition above on a Drupal 7 site resetting the destination query string worked form me.

unset($_GET['destination']);
drupal_static_reset('drupal_get_destination');
drupal_get_destination();

Thanks Mark!

share|improve this answer

Thanks for this, but for some reason this didn't work when I tried it. I got a fatal error -- the data sent in the example answer above doesn't satisfy the requirements of drupal_goto()

It may be because this answer is rather old, but I was able to get it work with this instead:

function mymodule_form_submit($form, &$form_state) {


  $form_state['redirect'] = array(
    'foo/bar', array(
      'query' => drupal_get_destination()
    )
  );

  unset($_GET['destination']);
  drupal_static_reset('drupal_get_destination');
  drupal_get_destination();

}

I know this violates this note:

you never want to overwrite the variable: other submit handlers might've defined their own redirects.

But, in this case, you do definitely want to overwrite the variable. You wouldn't be setting this value unless you wanted to disregard other module's set values. Also, I think you have to because of the way drupal_goto() works with the query parameter. This may also be why the original answer was throwing fatal errors on my site.

share|improve this answer

set form #action

global $base_path;
$form['#action'] = $base_path . '/node/'.$form_state['node']->nid.'/mytab';
share|improve this answer
    
-1 I think calling drupal_goto() in hook_node_insert() will screw things up (because drupal_goto() calls drupal_exit() preventing the new node from being saved). –  Andy Jul 22 at 10:52
    
true - in a node_insert hook .. (edited the answer) –  rémy Sep 11 at 20:34
    
This doesn't issue a redirect as OP asked, but submits the form to a different path. –  Andy Sep 16 at 8:52

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.