I am using hook_form_alter to add validation and submit handlers to the registration form:

<?php
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
  if (
$form_id == 'user_register_form') {
   
$form['#validate'][] = 'blah_register_validate';
   
$form['#submit'][] = 'blah_register_submit';
  }
}
?>

They were both working fine until I added the following hook:

<?php
function MYMODULE_user_login(&$edit, $account) {
 
drupal_goto('user'); 
}
?>

The validation function still works but the submit function gets bypassed completely - it doesn't get called at all by form_execute_handlers() in form.inc. As soon as I remove hook_user_login, it works again. Anyone have an idea why?

Update:

Ok, it seems it's normal that hook_user_login is called before the submit function, but I think you can have a submit function to fire before it? I've tried the below instead:

<?php
$form
['actions']['submit']['#submit'] = 'blah_register_submit';
?>

but it doesn't work.

Comments

seems that your

seems that your MYMODULE_user_login hook do the redirect before the new submit handler you added, try to move the goto statement to the end of the new submit handler and remove MYMODULE_user_login hook implementation.

Thanks, I'll try redirecting

Thanks, I'll try redirecting from the submit function, but I'm heading for big troubles if another module decides to redirect from hook_user_login().

The reason

The reason YOURMODULE_user_login() broke it is because drupal_goto() ends in exit; and nothing after it gets executed.

To run your custom submit handler before the default one, you can use:

<?php
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
  if (
$form_id == 'user_register_form') {
   
$form['#validate'][] = 'blah_register_validate';
   
array_unshift($form['#submit'], 'blah_register_submit');
  }
}
?>

(see php.net docs on array_unshift())

Ah ha! That makes sense and

Ah ha! That makes sense and seems like the fix I want. I'll give it a try.. thanks for the reply!

Using array_unshift does fire

Using array_unshift() does fire my submit function before the default submit. I didn't mention that I need to use the new user object in my submit function, so it does need to come after the default submit function.

Apparently, it's not good practice to add drupal_goto() in hook_user_login(). So instead, as discussed here http://api.drupal.org/api/drupal/modules%21user%21user.api.php/function/hook_user_login/7#comments, I added this to my hook_user_login() function instead:

<?php
/**
* Implements hook_user_login().
*/
function MYMODULE_user_login(&$edit, $account) {
 
$redirection = 'user';

  if (empty(
$_GET['destination'])
    && !
is_null($redirection)
    && (!isset(
$_POST['form_id']) || $_POST['form_id'] != 'user_pass_reset')) {
   
$_GET['destination'] = $redirection;
  }
}
?>

which does redirect the user, and I will just assume no other module will use drupal_goto(). Thanks for the help peeps!

It's best to use

It's best to use drupal_goto() as little as possible. I generally limit it to redirects for non-existent pages. For example, if I have a path: /companies/%company, and I don't have anything to show at the path: /companies, then I'll set up a redirect on that path using drupal_goto(). Using hook_user_login() is definitely a good way to go.

Jaypan We build websites

nobody click here