Form Redirection: A Special Case

Photo of Greg Harvey
Tue, 2008-04-08 20:32By greg

Most of you are probably familiar with using the Form API (either via hook_form_alter or when building your own form) to set the destination a user is sent to after submitting a form.

function mymodule_form_alter($form_id, &$form) {
if ($form_id == 'page_node_form') {
$form['#redirect'] = 'my/new/page';
}
}
?>

This usually works, but today I came across a special case.

What if you want to redirect users back to the referring page after they submit a new node? Sounds simple enough, right? You'd probably do something like this:

function mymodule_form_alter($form_id, &$form) {
if ($form_id == 'page_node_form') {
$form['#redirect'] = $_SERVER['HTTP_REFERER'];
}
}
?>

Wrong! In fact, not only is it not working, but it's actually taking you back to the submission form rather than your original destination or the default behaviour of the newly created node. Odd.

And here's why: http://drupal.org/node/63730

In a nutshell, your form is effectively submitted twice during the process of the Form API doing it's thing. The first time your redirect is correct, but the second time the referer is actually the node submission form, and this over-writes your original, intended redirect path.

Let's think about this. We can't do this while we build or alter our form, but one of the last things that happens in the Form API process is the form's submit function, so why can't we hijack that in our module? Well, we could. But we need the function called node_form_submit to fire on submit in order to create our content and it contains the redirect to the newly created node, which we'll need to somehow override, since we're not using the Form API any more. To do this you effectively have to keep a re-written copy of at least one core function in your own module, which sucks! You've just created code you have to maintain to keep step with Drupal updates. =(

But there is an approach which will allow you to achieve your redirect to the referring page, without duplicating any core functions or creating anything nasty which you have to maintain. I documented it here:
http://drupal.org/node/134000#comment-799369

Basically, you store the referring URL (either in the session or in a custom CCK field in your content type) and use the 'insert' operation of hook_nodeapi to handle your message setting and redirection. Perfect!

Note, this is not necessary in Drupal 6.x - there is a new form history part of the API allowing you to pick out the prior redirect and use it. Much neater! =)