visit
<?php
// Replace $user and $pass with strong values for production
$host = 'localhost';
$db = 'new_db';
$user = 'root';
$pass = '';
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$dsn = "mysql:host=$host;dbname=$db";
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
?>
<?php
// Get form field values
$fname = filter_input(INPUT_POST, 'fname', FILTER_SANITIZE_STRING);
$email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
$pwd = filter_input(INPUT_POST, 'password');
$pwd_confirm = filter_input(INPUT_POST, 'confirm-password');
?>
Make sure to not use FILTER_SANITIZE_STRING on the password as you don't invalidate a user's password. Someone, especially tech-savvy, people, might like having something like '<script>' as part of their password.
<?php
$activation_key = bin2hex(random_bytes(15));
$activation_link = '//www.example.com/activate?id='.$activation_key.'&name='.$fname;
?>
Generate an activation key and have new users confirm their account registration via email. This will greatly reduce the number of spam accounts. In my case, I used
bin2hex
to generate a random 15 character string to avoid any conflicts should a large number of users sign-up with your site. I also added the first name of the user to the string, which I can then verify server-side. <?php
// Check if passwords match
if ($pwd !== $pwd_confirm) {
$errors[] = "Passwords don't match";
}
// Check if password is secure
if (strlen($pwd) < 8) {
$errors[] = "Password not long enough! Must be at least 8 characters long";
}
// Check if username equals password
if ($fname === $pwd) {
$errors[] = "Your name cannot be your password!";
}
?>
<?php
// Check if email address exists in database
$email_query = $pdo->prepare("SELECT count(1) FROM users WHERE email = :email");
$email_query->bindParam(':email', $email);
$email_query->execute();
$email_found = $email_query->fetchColumn();
if ($email_found) {
$errors[] = "Your email address is associated with another account.";
}
?>
I'm also checking whether the email address already exists in the database. When you
SELECT
or INSERT INTO
values from/to your database, always use prepare statements and bind the parameters to avoid SQL injection. <?php
// If no errors, continue with user account creation
if (!$errors)
{
// Hash password
$hashed_password = password_hash($pwd, PASSWORD_DEFAULT);
// Create database entry
$create_account = $pdo->prepare("INSERT INTO users (first_name,email,password, activation_key) VALUES (:fname, :email, :password, :activation_key)");
$create_account->bindParam(':fname', $fname);
$create_account->bindParam(':email', $email);
$create_account->bindParam(':password', $hashed_password);
$create_account->bindParam(':activation_key', $activation_key);
$create_account->execute();
// Send out activation email
$to=$email;
$subject="Activate your account";
$from = '[email protected]';
$body='Thank you for creating your account, '.$fname.'. Please click on the following link to activate your account: <a href="'.$activation_link.'">'.$activation_link.'</a>';
$headers = "From:".$from;
mail($to,$subject,$body,$headers);
// Redirect user to the dashboard
header("Location: /dashboard.php");
exit;
}
?>
Last but not least, you want to send out the activation email. In this example, I used PHP's mail() function but you might want to go with PHPMailer instead. Also, you might want to use
http_build_query()
to build the activation string in case the user's first name is not url-compliant, e.g. uses ampersands. You can now exit the registration process and wait until the user activated his/her account or redirect them to the next page, e.g. dashboard. However, note that you probably want to initiate the session if you do go with a redirect.That's it!
Thomaso