How to Create PHP Registration System for Your Website

For most websites, it is required to build a registration system. These applications need to give access to only users who have gone through the registration process. If built correctly, this process keeps the system safe from fake/spam users.

In this article, we will create a registration system for a PHP-based website. While building a flow, we will cover the below points.

  • Validate Sign Up Form – The form must pass the validations like valid email, password entered twice and they must be the same.
  • Check for Spam – Exclude tons of spam entries using the honeypot in the form.
  • Email must be unique – The user can’t register more than once with a single email.
  • Email Verification – Once the user submits the registration form, email will be sent along with an activation link. This is a vital step to recognize real users.
  • Activate Account – A user must click on an activation link received in an email to activate their account.

All these steps make your system reliable and secure. Having said that, let’s start with the steps for it.

Create Database Table

For creating a registration system, you must store the user’s information in the database. Run the below SQL to create a users table. This table will store your user entries.

CREATE TABLE `users` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `fullname` varchar(255) NOT NULL,
 `email` varchar(255) NOT NULL,
 `password` varchar(255) NOT NULL,
 `activation_key` varchar(255) DEFAULT NULL,
 `status` int(11) NOT NULL DEFAULT 0 COMMENT '1=Active|0=Inactive',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Database Class (class-db.php)

When a user submits a form, their details should be stored using PHP and MySQL. For this, it needs to perform a few database operations.

  • insert_user() – Store user details into the database table. Must escape special characters from input strings.
  • email_exists() – Return false if email already exists into the system.
  • activate_account() – Set status flag to 1 which means the user activated their account.
<?php
class DB {
    private $dbHost     = "DB_HOST";
    private $dbUsername = "DB_USERNAME";
    private $dbPassword = "DB_PASSWORD";
    private $dbName     = "DB_NAME";

    public function __construct() {
        if(!isset($this->db)){
            // Connect to the database
            $conn = new mysqli($this->dbHost, $this->dbUsername, $this->dbPassword, $this->dbName);
            if($conn->connect_error){
                die("Failed to connect with MySQL: " . $conn->connect_error);
            }else{
                $this->db = $conn;
            }
        }
    }

    public function insert_user($arr_data = array()) {
        $keys = array_keys($arr_data);
        $values = array_values($arr_data);

        $db_values = '';
        $i = 0;
        foreach($values as $v) {
            $pre = ($i > 0)?', ':'';
            $db_values .= $pre. "'". $this->db->real_escape_string($v)."'";
            $i++;
        }

        $this->db->query("INSERT INTO users (".implode(",", $keys).") VALUES (".$db_values.")");
    }

    public function email_exists($email = '') {
        $sql = $this->db->query("SELECT id FROM users WHERE email = '$email'");

        if($sql->num_rows) {
            return true;
        }

        return false;
    }

    public function activate_account($activation_key = '') {
        $sql = $this->db->query("SELECT id, status FROM users WHERE activation_key = '".$activation_key."'");

        if ($sql->num_rows > 0) {
            $result = $sql->fetch_assoc();
            if ($result['status']) {
                return array('class' => 'success', 'message' => 'Your account is already activated.');
            } else {
                $sql = $this->db->query("UPDATE users SET status = '1' WHERE id = ".$result['id']." AND activation_key = '".$activation_key."'");

                return array('class' => 'success', 'message' => 'Your account is activated.');
            }
        } else {
            return array('class' => 'error', 'message' => 'Invalid URL.');
        }
    }
}

Make sure to replace placeholders DB_HOST, DB_USERNAME, DB_PASSWORD, DB_PASSWORD, DB_NAME with their actual values. I wrote a code for database connection in the constructor.

Installation of PHPMailer

The purpose of this tutorial is to show you how to build and secure a registration system for your website. Your sign-up form will be available on the Internet. It means there is a high chance of getting fake users. If you don’t build the system wisely, you will end up receiving tons of useless entries.

To avoid such a scenario, you must follow the user registration with email verification. Once a user fills the registration form, an email should go to their inbox along with the activation link. Only real users will receive this email. And once they activate their account, they should be able to log in to the system. If you notice, I kept the status column in the users table. It has 2 values.

  • 1 – Account is activated.
  • 0 – Account is inactive. This value is default.

While building a login system you must check the status value along with the user’s credentials. For more details, check the linked article.

As we need to send a verification email to the user, I am going to use the PHPMailer library to shoot our emails. Install the library using a Composer through the command:

composer require phpmailer/phpmailer

The benefit of using a PHPMailer library is that your emails go straight to the user’s inbox. Whereas, the emails sent through the default PHP mail() method might end up in spam.

The PHPMailer library works with SMTP servers. It means you need to get your SMTP credentials through which emails will be sent. The user can use different SMTP Servers like hosting, Gmail or Mailjet. Check out the below articles for how to use SMTP servers with PHP.

Form Validation with jQuery

When it comes to the HTML form, we should apply validations on form inputs. To apply validation, I am using the jQuery Validation plugin. Using this plugin, we make sure all form fields are filled before proceeding to the server-side. We also ask users to enter their password twice and both values must be equal.

Integrating the jQuery validation plugin is super easy. All you need to do is include 2 scripts. You also need to call validate() method on a form selector which we will do in registration.php file.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.3/jquery.validate.min.js"></script>

Registration Form (registration.php)

The registration.php file will have the HTML form, form validation, and server-side code. In the server-side code we will include:

  • Spam Checks – I’ll keep honeypot as a hidden field. This field must be empty(Bots filled this input). If it’s not empty then abort the process.
  • Email existence – If email is already available into the system, the user couldn’t proceed further.
  • Store users – If above checks pass, insert the user entries into the database.
  • Send activation email to the user.
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
 
require_once "vendor/autoload.php";
require_once 'class-db.php';

$arr_message = array();
if (isset($_POST['submit'])) {

    // check for spam
    if(!empty($_POST['honeypot'])) {
        die('Spams are not allowed!');
    }

    $db = new DB();
    if(!$db->email_exists($_POST['email'])) {

        $activation_key = sha1(mt_rand(10000,99999).time().$_POST['email']);

        $db->insert_user(
            array(
                'fullname' => $_POST['fullname'],
                'email' => $_POST['email'],
                'password' => md5($_POST['password']),
                'activation_key' => $activation_key,
            )
        );

        // send activate account email
        try {
            $mail = new PHPMailer(true);

            $mail->isSMTP();
            $mail->Host = 'SMTP_HOST'; // host
            $mail->SMTPAuth = true;
            $mail->Username = 'SMTP_API_KEY'; //username
            $mail->Password = 'SMTP_SECRET_KEY'; //password
            $mail->SMTPSecure = 'ssl';
            $mail->Port = 465; //smtp port
            
            $mail->setFrom('SENDER_EMAIL', 'SENDER NAME');
            $mail->addAddress($_POST['email'], $_POST['fullname']);
        
            $mail->isHTML(true);
            $mail->Subject = 'Activate Your Account';
            $mail->Body    = 'Hello '.ucwords($_POST['fullname']).',<br>
                            <p>Click the link below to activate your account.</p>
                            <a href="DOMAIN_URL/activate.php?key='.$activation_key.'">Activate Account</a><br>
                            Thanks,<br>Admin';
        
            $mail->send();
            $arr_message = array('class' => 'success', 'message' => 'We have sent an activation link on your email. Please activate your account.');
        } catch (Exception $e) {
            $arr_message = array('class' => 'error', 'message' => 'Email could not be sent. Mailer Error: '. $mail->ErrorInfo);
        }
    } else {
        $arr_message = array('class' => 'error', 'message' => 'Email is already exist.');
    }
}
?>

<?php if (!empty($arr_message)) { ?>
    <div class="<?php echo $arr_message['class']; ?>">
        <strong><?php echo $arr_message['message']; ?></strong>
    </div>
<?php } ?>

<style>
label.error {
    display: block;
    color: red;
}
</style>
<form method="post" id="frmRegistration">
    <p>
        <input type="text" name="fullname" id="fullname" placeholder="Enter Full Name" required />
    </p>
    <p>
        <input type="email" name="email" id="email" placeholder="Enter Email" required />
    </p>
    <p>
        <input type="password" name="password" id="password" placeholder="Enter Password" required />
    </p>
    <p>
        <input type="password" name="confirm-password" id="confirm-password" placeholder="Confirm Password" required />
    </p>
    <input type="hidden" name="honeypot" />
    <input type="submit" name="submit" value="Register" />
</form>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.3/jquery.validate.min.js"></script>
<script>
jQuery(function($) {
    $('#frmRegistration').validate({
        rules: {
            "confirm-password": {
                equalTo: '#password'
            }
        }
    });
});
</script>

Go ahead and give it a try. Upon filing a form, you should receive a verification email. Make sure you replace the placeholder DOMAIN_URL with the actual value. Next, let’s write a code to activate the account.

Activate User’s Account (activate.php)

In the class-db.php, we have already defined the activate_account() method. This method takes the activation key, checks it into the database. If the system finds the key is valid, it sets the status flag to 1 which means the user has activated their account.

In activate.php, we received the activation key from the GET request and passed it to the activate_account() for further processing.

<?php
require_once 'class-db.php';

if (!isset($_GET['key']) || empty($_GET['key'])) {
    die('Invalid URL');
}

$db = new DB();
$arr_result = $db->activate_account($_GET['key']);
?>

<div class="<?php echo $arr_result['class']; ?>">
    <strong><?php echo $arr_result['message']; ?></strong>
</div>

We are done with building a user registration system with email verification. You can use this flow and build your user management system. I would like to hear your thoughts and suggestions in the comment section below.

If you liked this article, then please subscribe to our YouTube Channel for video tutorials.

Leave a Reply

Your email address will not be published.