3 Steps Simple User Registration With Email Verification In PHP MYSQL

Welcome to a tutorial on how to create a user registration form with email verification, using PHP and MySQL. So you have decided to open up your website for user registration?

A simplified user registration system consists of the following basic components:

  1. First, a database to store registered users.
  2. Next, a PHP library to deal with the registration process.
  3. Finally, an HTML registration form and the confirmation page itself.

Let us walk through the exact details on how to do all of these in this guide – Read on to find out!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

 

TABLE OF CONTENTS

Download & Notes Registration Useful Bits & Links
The End

 

DOWNLOAD & NOTES

Firstly, here is the download link to the example code as promised.

 

EXAMPLE CODE DOWNLOAD

Click here to download the source code in a zip file – I have released it under the MIT License, so feel free to build on top of it if you want to.

 

QUICK NOTES

  • Create a new database and import 1-users.sql.
  • Edit 2-user-core.php.
    • Section F – Change the database settings to your own.
    • Do a quick search for @TODO – These are the sections that you will want to personalize and complete by yourself.
  • That’s all. Access 3a-register.php in the web browser.

If you spot a bug, please feel free to comment below. I try to answer questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

 

USER REGISTRATION WITH EMAIL VERIFICATION

All right, let us now get into the steps of creating a simple user registration system with email verification.

 

STEP 1) USERS DATABASE TABLE

1-users.sql
CREATE TABLE `users` (
  `user_id` int(20) NOT NULL,
  `user_email` varchar(255) NOT NULL,
  `user_password` varchar(255) NOT NULL,
  `user_activate` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `users`
  ADD PRIMARY KEY (`user_id`),
  ADD UNIQUE KEY `user_email` (`user_email`);
 
ALTER TABLE `users` MODIFY `user_id` int(20) NOT NULL AUTO_INCREMENT;
Field Description
user_id Primary key, auto-increment.
user_email The user’s email address. Unique field to prevent multiple registrations.
user_password The password.
user_activate Used to hold the “activation key”. If this field is null, then the account is already activated.

Just a simple table with 4 fields, feel free to add more of your own as required – Name, address, etc…

P.S. If you have an existing user table, it will probably make sense to just add a user_activate field.

 

 

STEP 2) PHP USER CORE LIBRARY

2-user-core.php
<?php
class Users {
  // (A) CONSTRUCTOR - CONNECT DATABASE
  private $pdo = null;
  private $stmt = null;
  public $error = null;
  function __construct () {
    try {
      $this->pdo = new PDO(
        "mysql:host=".DB_HOST.";dbname=".DB_NAME.";charset=".DB_CHARSET,
        DB_USER, DB_PASSWORD, [
          PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
          PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
        ]
      );
    } catch (Exception $ex) { exit($ex->getMessage()); }
  }

  // (B) DESTRUCTOR - CLOSE CONNECTION
  function __destruct () {
    if ($this->stmt !== null) { $this->stmt = null; }
    if ($this->pdo !== null) { $this->pdo = null; }
  }

  // (C) GET USER
  function get ($id) {
    $sql = sprintf("SELECT * FROM `users` WHERE `user_%s`=?", is_numeric($id)?"id":"email");
    $this->stmt = $this->pdo->prepare($sql);
    $this->stmt->execute([$id]);
    return $this->stmt->fetch();
  }

  // (D) REGISTER NEW USER
  function register ($email, $pass, $cpass) {
    // (D1) CHECK IF USER REGISTERED
    // @TODO - WHAT TO DO IF THERE IS AN EXISTING ACTIVATION?
    // ALLOW USER TO GENERATE NEW TOKEN & EMAIL AFTER SOME TIME?
    // MANUAL CONTACT ADMIN?
    $check = $this->get($email);
    if (is_array($check)) {
      $this->error = isset($check["user_activate"])
        ? "$email already has a pending activation."
        : "$email is already registered." ;
      return false;
    }
 
    // (D2) CHECK PASSWORD
    if ($pass != $cpass) {
      $this->error = "Passwords do not match.";
      return false;
    }
 
    // (D3) GENERATE NOT-SO-RANDOM TOKEN HASH FOR VERIFICATION
    $token = md5(date("YmdHis") . $email);

    // (D4) INSERT INTO DATABASE
    try {
      $this->stmt = $this->pdo->prepare(
        "INSERT INTO `users` (`user_email`, `user_password`, `user_activate`) VALUES (?,?,?)"
      );
      $this->stmt->execute([$email, password_hash($pass, PASSWORD_DEFAULT), $token]);
      $this->lastID = $this->pdo->lastInsertId();
    } catch (Exception $ex) {
      $this->error = $ex->getMessage();
      return false;
    }
 
    // (D5) SEND CONFIRMATION EMAIL
    // @TODO - CHANGE TO YOUR OWN MESSAGE + URL!
    $url = "http://localhost/3b-confirm.php";
    $msg = sprintf(
      "Visit this <a href='%s?i=%u&h=%s'>link</a> to complete your registration.",
      $url, $this->lastID, $token
    );
    if (@mail(
      $email, "Confirm your email", $msg,
      implode("\r\n", ["MIME-Version: 1.0", "Content-type: text/html; charset=utf-8"])
    )) { return true; } else {
      $this->error = "Error sending out email";
      return false;
    }
  }
 
  // (E) VERIFY REGISTRATION
  function verify ($id, $hash) {
    // (E1) GET + CHECK THE USER
    $user = $this->get($id);
    if ($user === false) {
      $this->error = "User not found.";
      return false;
    }
    if (!isset($user['user_activate'])) {
      $this->error = "Account already activated.";
      return false;
    }
    if ($user['user_activate'] != $hash) {
      $this->error = "Invalid token.";
      return false;
    }
 
    // (E2) ACTIVATE ACCOUNT IF OK
    try {
      $this->stmt = $this->pdo->prepare("UPDATE `users` SET `user_activate`=NULL WHERE `user_id`=?");
      $this->stmt->execute([$id]);
      $this->lastID = $this->pdo->lastInsertId();
    } catch (Exception $ex) {
      $this->error = $ex;
      return false;
    }
 
    // @TODO - (E3) SEND WELCOME MESSAGE IF YOU WANT
    // mail ($user["user_email"], "WELCOME!", "Welcome message here.");
    return true;
  }
}

// (F) DATABASE SETTINGS - CHANGE TO YOUR OWN!
define("DB_HOST", "localhost");
define("DB_NAME", "test");
define("DB_CHARSET", "utf8");
define("DB_USER", "root");
define("DB_PASSWORD", "");

// (G) NEW USER OBJECT
$USR = new Users();

Holy cow. That is a lot of code, but keep calm and look closely.

  • A & B – When the $USR = new Users() object is created, the constructor will connect to the database, the destructor closes the connection.
  • C – get() Get user by ID or email.
  • D – register() Step 1 of the registration process. Generates a random “activation key”, then sends the activation link to the user email.
  • E – verify() Step 2 of the registration process. After the user clicks on the link in the email, we verify the “activation key” and complete the registration process.
  • F & G – The database settings and user object. Doh.

 

 

STEP 3A) HTML REGISTRATION FORM

3a-register.php
<!-- (A) REGISTRATION FORM -->
<form method="post">
<input type="email" name="email" placeholder="Email" required value="jon@doe.com"/>
<input type="password" name="pass" placeholder="Password" required value="12345"/>
<input type="password" name="cpass" placeholder="Confirm Password" required value="12345"/>
<input type="submit" value="Go!"/>
</form>
 
<?php
// (B) PROCESS SUBMITTED REGISTRATION FORM
if (isset($_POST["email"])) {
  require "2-user-core.php";
  echo $USR->register($_POST['email'], $_POST['pass'], $_POST['cpass'])
    ? "Check your email and click on the activation link"
    : $USR->error ;
}
?>

Self-explanatory. The user fills in the registration form, we use register() to process and send out the activation link.

 

 

STEP 3B) CONFIRMATION PAGE

3b-confirm.php
<?php
require "2-user-core.php";
echo $USR->verify($_GET['i'], $_GET['h'])
  ? "Thank you! Account has been activated."
  : $USR->error ;
?>

Self-explanatory part 2. The user accesses the activation link and lands on this page – We verify the activation key and complete the process.

 

USEFUL BITS & LINKS

That’s it for this tutorial. Here are a few small extras and links that may help with your project.

 

BAREBONES START

Before the angry ugly troll things start to spit acid, this is but a barebones example. Some work still needs to be done before it is worthy of a production system.

  • A proper login page (links below).
  • An option to resend the confirmation email should the first one fails.
  • Maybe an auto-timeout mechanism, so users can request another confirmation after some time.

 

 

LINKS & REFERENCES

 

THE END

Thank you for reading, and we have come to the end of this guide. I hope that it has helped you with your project, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

24 thoughts on “3 Steps Simple User Registration With Email Verification In PHP MYSQL”

  1. Thanks so much. But i encounter a little problem, a confirmation email has been sent after registration but there’s no link to click and verify pls help

    1. Nothing to do with the script, it’s the spam filter. It is also common for most shared hosting to have a low reputation (marked as a possible email spambot).

Leave a Comment

Your email address will not be published. Required fields are marked *