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):
- 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'); ?> - Create another new PHP Code block for the registration form:
<?php print drupal_get_form('user_register'); ?> -
Install the Panels module, and add a new Panel using the two column layout.
-
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 wordregister. (More on that in a moment) Save the panel. -
Go to
Administer > Site Configuration > Error Reportingand 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.



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 :)
Post new comment