Creating a User Registration Form
This standalone registration page accepts a fictional username and password, validates both on the server, hashes the password and inserts a standard user account with PDO.
Database connection
The example expects includes/db.php to create a PDO object named $pdo.
Registration page
<?php
require __DIR__ . "/includes/db.php";
$username = "";
$errors = [];
$created = false;
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$username = trim($_POST["username"] ?? "");
$password = $_POST["password"] ?? "";
$confirm = $_POST["confirm_password"] ?? "";
if (!preg_match('/^[A-Za-z0-9_]{3,50}$/', $username)) {
$errors[] = "Username must be 3–50 letters, numbers or underscores.";
}
if (strlen($password) < 10) {
$errors[] = "Password must contain at least 10 characters.";
}
if ($password !== $confirm) {
$errors[] = "Passwords do not match.";
}
if (!$errors) {
$check = $pdo->prepare(
"SELECT user_id FROM users WHERE username = :username"
);
$check->execute(["username" => $username]);
if ($check->fetch()) {
$errors[] = "That username is unavailable.";
} else {
$insert = $pdo->prepare(
"INSERT INTO users (username, password, role)
VALUES (:username, :password, 'user')"
);
$insert->execute([
"username" => $username,
"password" => password_hash($password, PASSWORD_DEFAULT)
]);
$created = true;
$username = "";
}
}
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Create account</title>
</head>
<body>
<h1>Create account</h1>
<?php if ($created): ?>
<p role="status">Account created. You can now log in.</p>
<?php endif; ?>
<?php if ($errors): ?>
<div role="alert">
<p>Please correct the following:</p>
<ul>
<?php foreach ($errors as $error): ?>
<li><?= htmlspecialchars($error) ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<form method="post">
<label for="username">Username</label>
<input id="username" name="username" maxlength="50"
autocomplete="username" required
value="<?= htmlspecialchars($username) ?>">
<label for="password">Password</label>
<input id="password" name="password" type="password"
autocomplete="new-password" required>
<label for="confirm_password">Confirm password</label>
<input id="confirm_password" name="confirm_password" type="password"
autocomplete="new-password" required>
<button type="submit">Create account</button>
</form>
</body>
</html>
The form never accepts a role. Every public registration receives the server-controlled user role.
Test
Test valid input, short passwords, mismatched passwords, invalid usernames, duplicates and missing fields. Confirm that unsuccessful attempts create no database row.
Check
- Labels are associated with inputs.
- PHP validates all inputs.
- Username duplicates are handled.
- Password is hashed before insertion.
- Prepared statements are used.
- Registration cannot create an administrator.