In this first tutorial, you will learn how to:
Moreover, I will show you how bloody simple it is. Folks who follow this tutorial should already have:
Overriding is always done in the theme’s template.php file (if you don’t have a template.php file, you may create a it now). Obviously, before you can override anything, you must first locate what you are trying to override. The best way to do this is to search a module for the $form variable.
Of course, the user module has no shortage of forms. However, eventually we come across function user_login:
(modules/user.module on line 868).
<?php
function user_login($msg = '') {
//…(omitted scary code)
return drupal_get_form('user_login', $form);
}
?>So there you have it, the top and the bottom of the function. That’s all you really need to override it. Here’s the code:
<?php
function phptemplate_user_login($form) {
return _phptemplate_callback('user_login', array('form' => $form));
}
?>Notice the scary looking _return_phptemplate_callback(‘user_login’,array(‘form’ => $form));? Oooohhh… scary… gonna cry? Your choice is simple, either you can hide under a blanket, or you can take a look at the pattern:
_return_phptemplate_callback(‘[the name of your .tpl.php file]’,array(‘[the name of the variable sent to your .tpl.php file]’ => [‘the actual variable that was returned from the function this code calls’]));
Before moving on, I want to remind you that you aren’t stupid. This doesn’t make immediate sense to anyone. So relax, and look for patterns in colors: they hold some big keys.
I’m now going to ask you to create a new tpl.php file called user_login.tpl.php.
So just to review your theme’s files should be:
/themes/yourtheme/template.php
/themes/yourtheme/user_login.tpl.php
Insert the code:
<h1>Hello world!</h1>
<?php
print_r(form_render($form));
?>If all has gone according to plan, www.example.com/user/login now greats you with:

Amazing how sometimes, things can just start to make sense. YOu don’t need to understand it; you don’t even need to agree with it. Just accept it, and continue.
The user login form usually needs some additional info, or links that drupal does not provide by default. If you were an amateur, you’d probably hardcode that extra info into the theme. However, since you’re an expert, you’re going to stick an editible node into the login area instead. Title your node, “Join the Revolution”, and stick this in the body:
<p>"The temptation to quit will be greatest just before you are about to succeed."
<em>-an old Chinese saying</em></p>Now, let’s stick that node in the login form. This is going to be a two part process
<?php
function phptemplate_user_login($form) {
/* PAY ATTENTION, $login_node is a fully loaded node.
Note that in my tutorial site's case, the node's ID was 1
(the URL is example.com/node/1… …"1" = my node's ID).
*/
$login_node = node_load(array( 'nid' => 1));
return _phptemplate_callback('user_login', array(
'form' => $form,
// LOOK! this sends the $login_node variable to user_login
'login_node' => $login_node
));
}
?><h1><?php print $login_node->title; //Yes, that was the node's title: ?></h1>
<?php
//Yes, that is the node's body:
print $login_node->body;
//try uncommenting this code below to see what else is available:
// print "<pre>"; print_r(get_object_vars($login_node));print "</pre>";
?>
<?php
print_r(form_render($form));
?>And like magic, there is your node — AND it can be changed by a non-programmer.

Say we wanted to display our form horizontally. CSS could do most of the heavy lifting. Unfortunatly, the descriptions (e.g. “enter your username here”) kind of get in the way. If we were amateurs, we’d copy and paste the form directly into our template, and call it a solution. But remember kids, we’re experts and do things the right way ;-).
The array_values for the username and password forms are as follows:
[13] => Array
(
[#type] => password
[#title] => Password
[#description] => KILL ME KILL ME KILL ME
[#required] => 1
[#attributes] => Array
(
[tabindex] => 2
)
[#tree] =>
[#parents] => Array
(
[0] => pass
)
[#weight] => 0.001
[#input] => 1
[#size] => 30
[#name] => edit[pass]
[#id] => edit-pass
[#value] =>
)
As you can see, #description really wants to be killed in this case. As you are no doubt aware, this is going to take a lot of work to do… I mean, look WHAT we have to do to kill it.
<?php
function phptemplate_user_login($form) {
$login_node = node_load(array( 'nid' => 1));
//We're removing the description text before the form is rendered
$form['pass']['#description'] = '';
$form['name']['#description'] = '';
//A friendlier name for our submit button:
$form['submit']['#value'] = 'Get yer ass in here';
return _phptemplate_callback('user_login', array(
'form' => $form,
'login_node' => $login_node
));
}
?>You’ll also note that we changed the submit button to “get yer ass in here”. That is because we understand the importance of friendly interfaces. Now let’s rearrange our user_login.tpl.php file, and add some CSS:
<div id="user_login">
<h1><?php print $login_node->title; //Yes, that was the node's title: ?></h1>
<?php
//try uncommenting this code below to see what else is available:
// print "<pre>"; print_r(array_values($form));print "</pre>";
print_r(form_render($form['name']));
print_r(form_render($form['pass']));
print_r(form_render($form));
?>
<?php
//Yes, that is the node's body:
print $login_node->body;
//try uncommenting this code below to see what else is available:
// print "<pre>"; print_r(get_object_vars($login_node));print "</pre>";
?>
</div>#user_login {
font-size:11px;
padding:6px 12px;
}
#user_login p {
font-size:9px;
}
#user_login h1,
#user_login .form-item,
#user_login label,
#user_login input.form-text {
display:inline;
}Folks, this is where it gets hard. Now, we want to display our new login form on every page. Be strong, you can do this: 1)open up page.tpl.php, and insert the following code directly below the “body” html tag.
<body>
<?php print $user_login_form;?>Now we add the final step, we call the user_login() function from template.php, and pass it to page.tpl.php. Here it is.
<?php
function phptemplate_user_login($form) {
$login_node = node_load(array( 'nid' => 1));
//We're removing the description text before the form is rendered
$form['pass']['#description'] = '';
$form['name']['#description'] = '';
//A friendlier name for our submit button:
$form['submit']['#value'] = 'Get yer ass in here';
return _phptemplate_callback('user_login', array(
'form' => $form,
'login_node' => $login_node
));
}
// Will explain later.
function _phptemplate_variables($hook, $vars) {
global $user;
switch($hook) {
case 'page' :
// SUPER IMPORTANT: These rules prevent you from crashing your server :-)
if (arg(0) != "user" && $user->uid == "0") {
$vars['user_login_form'] = user_login($msg = '');
}
break;
}
return $vars;
}
?>VERY IMPORTANT: YOU MUST DISABLE ANY ACTIVE user login BLOCKS — otherwise, it won’t work.
And the final product:

As the title of this tutorial suggests, this is merely an introduction. Expect part 2 in the near future.
Questions are encouraged. Also, I’ve provided a working version of this tutorial’s code.