2

I am trying to add an additional submit handler to the user login form, to simply redirect users to the page they were on before landing on the login page (/user/login).

I have the following code attempting to store the current path/destination in the $form_state storage which is working as I expected when the original form_alter is run on render as it alters the redirect property of form_state to the previous page.

However, when the form is submitted, the form_alter is fired again, but this time the form_state storage is empty, thus the current_path/destination is now set to /user/login which is not where the user should be redirected to.

Here is the code I have at the moment, any help would be appreciated as to why the form_alter is run again on form submit:

function MODULE_form_user_login_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $form['#submit'][] = '_module_custom_user_login_form_submit';
  if (is_null($form_state->get('redirect_dest'))) {
    $destination = $_SERVER['HTTP_REFERER'];
    $form_state->set('redirect_dest', $destination);
  }
}

function _module_custom_user_login_form_submit($form, FormStateInterface &$form_state) {
  $destination = $form_state->get('redirect_dest');
  $form_state->setRedirect($destination);
}
1

I think the chain of events is different. The form gets cached with no or the wrong redirect_dest set. Then the form is submitted and redirected to the form itself. This is now a new form build, because you didn't request a rebuild. Only in a rebuild you keep the form_state.

Solution:

Drupal has the feature to redirect built in. Add the destination on the page linking to the user login:

Url::fromRoute('user.login', [], ['query' => $destination])

Edit (new module):

To add the destination automatically you can use this module:

https://www.drupal.org/sandbox/gnuget/2824414

This is a js solution, so it doesn't interfere with caching. I think in this case you can use a sandbox module, because the site won't break if the js code stops working.

  • Thanks for helping, I have already tried the module recommended, but the PHP snippets feature has been removed in the Drupal 8 port. I don't think that it has anything to do with a rebuild, as it is simply the user login form, not a multi-step form. My understanding was that hook_form_alter is only fired when the form is rendered, why is it when I have a breakpoint inside form_alter it is hit again before the breakpoint in the submit function when submitted? I would understand hitting it again if I were redirected back to the same page, but surely the submit handler must be hit first? – Jon Hockley May 31 '17 at 10:24
  • Most times the form build/alter is not fired, when a form is rendered, because of caching. But it is on POST requests, because these are not cached. – 4k4 May 31 '17 at 12:18
  • I found a module that adds the destination in javascript, so there shouldn't be any problems with caching, see edit. – 4k4 May 31 '17 at 12:37
  • Thanks for the module link, it's helping a lot more than the other ones I've already tried. – Jon Hockley May 31 '17 at 13:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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