Sign up ×
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.

share|improve this question

3 Answers 3

up vote 22 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));

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';


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

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()



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
This answer helped me realize that in some circumstances, you may want to completely override the $form_state['redirect'], or you may get a WSOD with competing redirects. – tyler.frankenstein Sep 15 at 3:31

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 '14 at 10:52
true - in a node_insert hook .. (edited the answer) – rémy Sep 11 '14 at 20:34
This doesn't issue a redirect as OP asked, but submits the form to a different path. – Andy Sep 16 '14 at 8:52

protected by kiamlaluno Oct 27 at 10:25

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

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