Drupal: Combining the Login and Registration Forms

It’s easy to take Drupal’s built-in user management features for granted… out of the box, you can configure your site to allow user registrations, reset forgotten passwords, and handle user logins. We had a use case where we wanted to combine the login and registration forms into a single landing page for anonymous users, to encourage users without an account to sign up with a single click rather than hiding the registration form behind another link.

There are many ways to skin a cat in Drupal, and the more familiar you get with the way Drupal and its many contributed modules work you start to realize that it’s possible to do things like set up a combination login/registration screen with little if any custom coding.

Here’s what we did (Your mileage may vary - on some sites it may not be appropriate to use executable PHP blocks, but our permission scheme accomodated it nicely):

  1. Create a new block (Admin > Build > Block > Add Block). Set the input format to PHP Code, and give it the following contents, which will display the standard user login form:

    <?php  print drupal_get_form('user_login');  ?> 
  2. Create another new PHP Code block for the registration form:
    <?php  print drupal_get_form('user_register');  ?> 
  3. Install the Panels module, and add a new Panel using the two column layout.

  4. Put the login form block in the left column and the registration form block in the right column. Give the panel a path like myapp/register- it’s very important that the second part of the path contain the word register. (More on that in a moment) Save the panel.

  5. Go to Administer > Site Configuration > Error Reporting and set the default 403 (Access Denied) error page to the path of the Panel you just created. This means that whenever an anonymous user encounters a page requiring authentication, they will get the login/registration form instead of the somewhat rude, default “Access Denied” error.

And that’s it. Zero custom code required, and we had our combination login/registration screen ready to go. We did choose to write a small module implementing hook_form_alter() to streamline the forms a little bit, making fields shorter, eliminating some of the field descriptions, and adding a link to the password reset form. Combined with some CSS styling, the result is pretty sharp:

So, why does the Panel’s path have to have two items, the second one always being “register”? The answer is in the core user.module file, in the _user_edit_validate() function:

<?php
// Validate the username:
if (user_access('change own username') || user_access('administer users') || arg(1) == 'register') {
if ($error = user_validate_name($edit['name'])) {
form_set_error('name', $error);
}
else if (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != %d AND LOWER(name) = LOWER('%s')", $uid, $edit['name'])) > 0) {
form_set_error('name', t('The name %name is already taken.', array('%name' => $edit['name'])));
}
else if (drupal_is_denied('user', $edit['name'])) {
form_set_error('name', t('The name %name has been denied access.', array('%name' => $edit['name'])));
}
}
?>

This chunk of code is responsible for making sure a submitted user name isn’t already taken, and the only way it gets called when the user_register form is submitted is if arg(1) is “register”, as is the case when signing up from the standard /user/register path. If you give your combination login/register panel a path whose second item is not “register”, it will still work, but the system won’t catch duplicate user name requests, resulting in the behavior reported at http://drupal.org/node/148525.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

I could be wrong, but isn't

I could be wrong, but isn't this easy to do with panels?

core patch

I would like to see this incorporated into the default 403 page in core.

Thanks...

Thanks for the good write-up. This should should certainly be part of Drupal core and the default 403 page.

Thanks for sharing. Great

Thanks for sharing. Great for usability but i see my site header again with an Access Denied message.
hidrolik pto

Great idea

Thanks for sharing this - it's a great idea.

I hesitate to ask for more when you've been generous in sharing this suggestion, but would you mind sharing the code you used in the small custom module to change the layout of the forms?
My username and password fields are way too long and overlap onto the other panel column. I guess that's what you're saying your module fixes.

Understood if you don't want to share it as well, but if you do - thanks!

+1 for core in some form or other (presumably without panels requirement)

cheers
Steve

I love this tutorial.Great

I love this tutorial.Great for usability! Any chance we could get your hook form alter code? Thanks again!

Yeah, it is really helpful

Yeah, it is really helpful and I managed to do it today!

Getting Error when i had created login and registration page

Hi,
Please find the below error show in the browser.

Redirect Loop

Firefox has detected that the server is redirecting the request for this address in a way that will never complete.

The browser has stopped trying to retrieve the requested item. The site is redirecting the request in a way that will never complete.

* Have you disabled or blocked cookies required by this site?
* NOTE: If accepting the site's cookies does not resolve the problem, it is likely a server configuration issue and not your computer.

How did you manage to get back into your website in the end?

How did you manage to get back into your website in the end?

I have the same problem, but can not log back in to remove the block now.

Any tips would be great as I would like to get my site back up asap.

Many thanks

Log Out

go to yoursite.com/logout

Delete the block

Log into the database and go to the blocks table and delete the two rows you have added that are causing the problem.

Without Panels FYI

FYI
I also did this for an intranet page using tables with the PHP in each table on a page instead of panels if your not comfortable installing panels. I know that's obvious to most but just in case..... : )

If you don't want panels you

If you don't want panels you could also just use css - float the login block left and the register block right and set them both to a width of say 45%.

Thanks for the idea - i've changed my login and register page to this

Access Denied Page Below Panel

I implemented this great suggestion, but when I try to access a page that requires authentication I get a strange result. I see the panels page described above, and then I see my site header again with an Access Denied message below it. What is causing this unusual behavior?

Thanks.

Cumbersome Registration process

I have been trying to achieve the same in Drupal. We all know that websites land up loosing many visitors due to the cumbersome registration processes. We ourselves at times skip the website and dont want to spend much time on all these.
So having the same landing page as you mentioned is a good idea and your post just makes it as simple as it could be.
Thanks for this great post, you just made my life much easier..

Nice write up. Best

Nice write up.
Best regards!
Owner of Kredyt Samochodowy site.

That is really nice to have

That is really nice to have will not waste the visitors time and working around to register would be easy for them..

Missing the obvious?

This great but I think you are ignoring the fact that the 403 page is required for when the user is not allowed to access some part of the site .. eg non-administrative user trying to access /admin. In that case presenting a login form when 1. they are already logged in and 2. really should be seeing an access denied message is not such a good idea.

"There are many ways to skin

"There are many ways to skin a cat in Drupal, and the more familiar you get with the way Drupal and its many contributed modules work you start to realize that it’s possible to do things like set up a combination login/registration screen with little if any custom coding." So true.. thats what makes it great.. Thanks for sharing your code! Kate

Missing the obvious?

"This great but I think you are ignoring the fact that the 403 page is required for when the user is not allowed to access some part of the site .. eg non-administrative user trying to access /admin. In that case presenting a login form when 1. they are already logged in and 2. really should be seeing an access denied message is not such a good idea."

I don't think this is missing the obvious. Access denied messages aren't a bad idea. That doesn't even make sense. It shows the user they aren't allowed to do that.

--Jack Bristoll

Redirect Loop

For some reason I cannot get it to work, does anybody have any idea how to solve the problem with the redirect loop? As long as you do not put both forms together on one page, everything works great, but once you enable both of them you get this "redirect loop" error... I really have no idea what to do...

Anybody??

Redirect problem possibly because...

I wonder if all these redirect loop issues are down to line 1241 (Drupal 6.14) which is as follows:


// If we are already logged on, go to the user page instead.
if ($user->uid) {
drupal_goto('user/'. $user->uid);
}

combined with (when you drupal_get_form for both login and registration forms) line 2399 which is as follows:


// If we aren't admin but already logged on, go to the user page instead.
if (!$admin && $user->uid) {
drupal_goto('user/'. $user->uid);
}

Is it possible that these error loops are occurring because the user is already logged in? The very act of calling both forms is possibly trying to redirect (drupal_goto) already logged in users twice to 'user/userid'? Just wondered if this might be the case? If so, a simple 'if' statement of :


if ($user->uid == 0){
...drupal_get_forms...
}

would probably resolve this?

_user_edit_validate() and the path

Looks like the requirement for the path's arg(1) to be 'register' is no longer in effect (as of Drupal 6.12 at least, maybe earlier).

Thanks!

This works great without panels

As Chris Burgess points out, arg(1) is no longer needing to be 'register' for Drupal 6.14 and simply using drupal_get_form('user_login') and drupal_get_form('user_register'), without Panels, takes care of things nicely for us so far.

thanks for the article and comments

Thanks for the detailed steps

Andy, thanks for the tips! I'm helping my wife with her drupal site and your instructions really came in handy. She's planning to setup a private membership area with it and I was just figuring how to deal with the login issue. Please keep up the great work!

I've subscribed to your blog :)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd><p><div> <br><img>
  • Lines and paragraphs break automatically.

More information about formatting options

Verification
This question is for testing whether you are a human visitor and to prevent automated spam submissions.