Here's a rewrite of the code (untested) with the suggestions factored in. I also did away with exit(), which has the same problems as die() when outputting HTML. There are a few parts that need to be filled in (marked with "..."). For examples of the class LocalDB used below, see "Re: Display all that would be secret while Mysql is broken" and "Re: [PHP] MySQL and PHP" (there are quite a few other threads with examples; search them out, if you're curious). There is still room for improvement. For example, you could define the form in one place, and use that info to both construct the form and validate it. You should also separate out the database access code into a separate data access layer. These both could be considered part of a larger improvement: separating concerns to reduce coupling.
Code:
CREATE TABLE meanbot_ta.users (
id INT PRIMARY KEY AUTO_INCREMENT,
firstname VARCHAR(64) NOT NULL,
lastname VARCHAR(64),
email VARCHAR(256) NOT NULL UNIQUE,
blah CHAR(40) NOT NULL,
llogin TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
HTML Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Account Signup</title>
<meta content="text/html; charset=unicode" http-equiv="Content-Type" />
<style type="text/css">
form#signup {
float: left; /* shrink-wrap */
background-image: url(backer.jpg);
}
label {
text-align: right;
float: left;
background-color: #CCC;
min-width: 8em;
margin-right: 0.25em;
padding: 0 0.25em;
}
input {
display: block;
}
input[type="submit"] {
margin-left: 12em;
}
</style>
</head>
<body>
<form method="post" name="signup" action="logincreate.php">
<fieldset>
<legend>Get started here.</legend>
<label for="firstname">First Name</label>
<input id="firstname" name="firstname" value="" size='25'/>
<label for="lastname">Last Name</label>
<input id="lastname" name="lastname" value="" size='25'/>
<label for="email">E-Mail</label>
<input id="email" name="email" value="" size='25'/>
<label for="password1">Password</label>
<input id="password1" name="password1" value="" size='25' type='password'/>
<label for="password2">Confirm password</label>
<input id="password2" name="password2" value="" size='25' type='password'/>
<input id="submit" name="submit" value="Sign Up" size='25' type='submit'/>
</fieldset>
</form>
</body>
</html>
PHP Code:
<?php
// for class LocalDB
require_once('LocalDB.php');
$fields = array(
'firstname' => array('filter' => FILTER_SANITIZE_STRING, 'label' => 'first name'),
'lastname' => array('filter' => FILTER_SANITIZE_STRING, 'label' => 'last name'),
'email' => array('filter' => FILTER_VALIDATE_EMAIL, 'label' => 'e-mail address'),
'password1' => array('filter' => FILTER_UNSAFE_RAW, 'label' => 'password'),
'password2' => array('filter' => FILTER_UNSAFE_RAW, 'label' => 'password confirmation'),
);
if (isset($_POST['submit'])) {
// Validation
$errors=array();
$data = filter_var_array($_POST, $fields);
foreach ($data as $field => $value) {
if (is_null($value)) {
$errors[$field] = "You must enter your {$fields[$field]['label']}.";
} elseif (False === $value) {
// validation failed
if (empty($_POST[$field])) {
$errors[$field] = "You must enter your {$fields[$field]['label']}.";
} else {
$errors[$field] = "'{$_POST[$field]}' isn't a valid {$fields[$field]['label']}.";
}
} else {
$user[":$field"] = $value;
}
}
// password confirmation test
if ($data['password2'] && $data['password1'] != $data['password2']) {
$errors['password2'] = "Passwords do not match.";
} else {
unset($user[':password2']);
}
if ($errors) {
// redisplay form, with errors beside each input field that failed validation. Make
// sure to refill form values with data that user entered.
...
} else { // validation successful
try {
$db = LocalDB::connect();
$createUserQuery = $db->prepare("INSERT INTO meanbot_ta.users (firstname, lastname, email, blah) VALUES (:firstname, :lastname, :email, SHA(:password1))");
$createUserQuery->execute($user);
// Creation successful. Display success message, log in user, and display profile editing form.
?>
<p>Your new account has been successfully created. You can start filling out your profile below.</p>
<?php
...
/* e.g.:
login($user[':email'], $user[':password1']);
include('edit/profile.php');
*/
} catch (PDOException $exc) {
switch ($createUserQuery->errorCode()) {
case '23000': // duplicate primary key; user exists
?>
<p class="error">An account already exists for this e-mail address. Please use a try a different email.</p>
<?php
break;
default: // internal error. Inform user & log
?>
<p class="error">I had an internal error when trying to communicate with the database. It's been logged, and we'll look into it. Please try again later.</p>
<?php
// log error
...
break;
} /* end switch errorCode */
} /* end catch PDOException */
} /* end validation successful */
} /* end form submitted */
?>