Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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.

set form #action

global $base_path;
$form['#action'] = $base_path . '/node/'.$form_state['node']->nid.'/mytab';
Licensed under: CC-BY-SA with attribution
Not affiliated with drupal.stackexchange
scroll top