dots Created with Sketch.
Yogesh Chauhan's Blog

PHP Login System using PDO Part 1: Create User Registration Page

in PHP on December 27, 2019

In this post we will see how to create a registration page so that user can create accounts. I will demonstrate the code chunks one by one and you can checkout the DEMO from the link provided at the end of this article.

Before we move to PHP part, I will create a table in my database to insert the user inputs like username, password, email address etc.

So, let's go ahead and create a table in database.

I will use phpmyadmin to crate the table "users". Use this code to create the table:


DROP TABLE IF EXISTS `users`;
CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `password` varchar(255) NOT NULL,
  `created_at` datetime DEFAULT CURRENT_TIMESTAMP,
  `email` varchar(50) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`),
  UNIQUE KEY `email` (`email`)
);

In the SQL query above I am creating a table "users" and adding 5 columns into it.

Read more about "create table" command in this following blog post:

Essential SQL Commands We Need to Know

The size of column named 'id' is temporary, you need to change the size as per number of users you are expecting to have. Same for other column names. You can always choose the size.

REMEMBER: Make sure you don't keep the size of "password" column less than 60 as I am going to show you how to store passwords using password hash and it will require size of at least 60 characters. 

Read more about password hash in this following blog post:

How to Use password_hash and password_verify to Secure Your User's Data (Especially Passwords)?

Also, we need column 'id' as a primary key which will be unique number and will be used as a reference to this table in future tables. Column "created_at" has a default value of current time stamp and every time we insert data, the SQL will automatically insert current time in that cell for the particular row. So, that we will know when the user account has been opened. Last thing in the table, we will keep the "username" and "email" columns as unique key because we don't want a same user with many accounts. So, if the user provided an unique email address and an unique username, he/she is good to go. Otherwise, system will show an error of duplicate user, which we will do using PHP.

Okay. First step is done. Now let's move to second step in which we need database connection established in the beginning so that we can perform INSERT operation in SQL using that connection.

You can establish connection using following code:


<?php
define('server', 'localhost');
define('user_name', 'root');
define('password', '');
define('database', 'the-coding-yogi');
 
try{
    $pdo = new PDO("mysql:host=" . server . ";dbname=" . database, user_name, password);
    // Set the PDO error mode to exception
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e){
    die("ERROR: Could not connect. " . $e->getMessage());
}
?>

Learn more about establishing connections in following blog post:

Learn to Establish Connection using MySQLi (object-oriented), MySQLi (procedural) and PDO with Example Code

Now, let's just create a simple form in HTML.

You can apply style-sheet if you want. I am just going to show you the HTML code over here.


<h2>Sign Up</h2>
    <h4>Please fill this form to create an account.</h4>
    <form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post">
        <div class="row" <?php echo (!empty($user_name_error)) ? 'has-error' : ''; ?>">
            <div class="label_class"><label>Username</label></div>
            <div class="input_class"><input type="text" name="user_name" value="<?php echo $user_name; ?>" required></div>
            <span><?php echo $user_name_error; ?></span>
        </div> 
        <div class="row" <?php echo (!empty($email_error)) ? 'has-error' : ''; ?>">
            <div class="label_class"><label>Email Address</label></div>
            <div class="input_class"><input type="email" name="email" value="<?php echo $email; ?>" required></div>
            <span><?php echo $email_error; ?></span>
        </div>    
        <div class="row" <?php echo (!empty($password_error)) ? 'has-error' : ''; ?>">
            <div class="label_class"><label>Password</label></div>
            <div class="input_class"><input type="password" name="password" value="<?php echo $password; ?>" required></div>
            <span><?php echo $password_error; ?></span>
        </div>
        <div class="row" <?php echo (!empty($confirm_password_error)) ? 'has-error' : ''; ?>">
            <div class="label_class"><label>Confirm Password</label></div>
            <div class="input_class"><input type="password" name="confirm_password" value="<?php echo $confirm_password; ?>" required></div>
            <span><?php echo $confirm_password_error; ?></span>
        </div>
        <div class="row" >
        <div class="input_class">
            <input type="submit" value="Submit">
            <input type="reset" value="Reset"></div>
        </div>
    </form>

In the code above, I have created a simple form in which we will ask user for 4 inputs. First one will be username, second email address, third password and at last repeat password so that user will write down the correct password.

We need repeat password field for one more reason as well and that is we have input type as password, which will hide the user inputs so if by any chance user think of a password and make a mistake in entering it, he/she will know when they type it again in repeat field. 

Same as password input, our email input has type email which will force user to enter an email address in a valid format.

In the value attribute, I am adding the values entered by the user itself using a simple PHP echo statement. 

You can see there are span tags after every input elements which I have kept to show user whenever there is an error. You'll learn more about it moving forward. It's a good approach to show user errors at the nearby spot where the errors have actually occurred.

Also, don't worry about the class you see in the form. They are from my stylesheet.

Now, lets see what will happen when user submits the form.

First we went to check if the field are empty or not, which we are already doing by using HTML attribute "required" in the HTML form itself.

Read more about useful HTML attributes in this blog post:

Some interesting HTML Input Attributes to remember

So, now we are assured that the form won't be empty at all as HTML won't even let user submit it without filling it up.

Let's declare the errors we just saw in span tags in the HTML forms. We will initialize them with empty values.


$user_name = $email = $password = $confirm_password = "";
$user_name_error = $email_error = $password_error = $confirm_password_error = "";

Let's see what to do when we have all the data submitted by user. First, we need to make sure that we don't have an user with same username or same email address. For that we will check out database for matching entries. The following code will check if we have a similar username in our database and if so, it will generate an error.


if($_SERVER["REQUEST_METHOD"] == "POST"){
 
    $sql = "SELECT id FROM users WHERE username = :user_name";
    
    if($stmt = $pdo->prepare($sql)){
        $stmt->bindParam(":user_name", $param_user_name, PDO::PARAM_STR);
        $param_user_name = trim($_POST["user_name"]);
        
        if($stmt->execute()){
            if($stmt->rowCount() == 1){
                $user_name_error = "This username is already taken.";
            } else{
                $user_name = trim($_POST["user_name"]);
            }
        } else{
            echo "I apologize! Something went wrong. Please try again later.";
        }
    }

//code continues

So, we have the connection established already so we will prepare the SQL query and pass it to that connection to check if we have same username in the database. If so, we will show user an error. If not, we will save that username into a variable and use that variable into INSERT query.

Now, we will check if the email address entered by the user is in the database already or not. We will use following code for that which has similar functionality as the previous code.


$sql = "SELECT id FROM users WHERE email = :email";
    
    if($stmt = $pdo->prepare($sql)){
        $stmt->bindParam(":email", $param_email, PDO::PARAM_STR);
        
        $param_email = trim($_POST["email"]);
        
        if($stmt->execute()){
            if($stmt->rowCount() == 1){
                $email_error = "This email is already taken.";
            } else{
                $email = trim($_POST["email"]);
            }
        } else{
            echo "I apologize! Something went wrong. Please try again later.";
        }
    }

//code continues

Now, we are sure that we won't have any duplicate entries in our database.

Let's make some password requirements a bit tough for security reasons. I am just going to show you one example of minimum password length. You can have many strict requirements to make it really strong password.

The following code will ask for a minimum length of 8 for password and if user enters less than 8 characters then it will show an error i that span tag under the password field.


if(strlen(trim($_POST["password"])) < 8){
        $password_error = "Password must have at least 8 characters.";
    } else{
        $password = trim($_POST["password"]);
    }

//code continues

We are using strlen function from PHP to count the length of the password entered by user. If it meets the minimum length requirement then we will temporary save it to a variable and insert into the database later on.

Why am I saving all the inputs into a temporary variables? By doing so, I am checking one by one, all the requirements. For example, no similar username, no similar email, minimum 8 characters in passwords etc. So, that if everything is satisfied then I will be sure of the standard I've set for the new user and I'll take that user into the system.

Now, lets check for one more requirement which is that the passwords in the first and second fields, MUST match. We will check that using following code.


$confirm_password = trim($_POST["confirm_password"]);
    if(empty($password_error) && ($password != $confirm_password)){
        $confirm_password_error = "Password did not match.";
    }

//code continues

The code above will show an error if they don't match. If they do, then nothing as we have already saved that input in a temporary variable.

Now, for the final time we will make sure that all the errors are empty as we'd declared in the beginning and if they are empty then we will insert the data into the system.


   if(empty($user_name_error) && empty($password_error) && empty($confirm_password_error) && empty($email_error)){
        
        $sql = "INSERT INTO users (username, password, email) VALUES (:user_name, :password, :email)";
         
        if($stmt = $pdo->prepare($sql)){
            $stmt->bindParam(":user_name", $param_user_name, PDO::PARAM_STR);
            $stmt->bindParam(":password", $param_password, PDO::PARAM_STR);
            $stmt->bindParam(":email", $param_email, PDO::PARAM_STR);
            
            $param_user_name = $user_name;
            $param_password = password_hash($password, PASSWORD_DEFAULT);
            $param_email = $email;

            if($stmt->execute()){
                $alert = "Your account has been created.";
                echo "<script type='text/javascript'>alert('$alert');</script>";
            } else{
                $alert = "I am sorry! There was some error. Try again please.";
                echo "<script type='text/javascript'>alert('$alert');</script>";
            }
        }
    }
    unset($pdo);
}
?>

Finally we will insert the data into the system. You can see I've used password hash to save passwords into the system. 

Read more about password hash in this following blog post:

How to Use password_hash and password_verify to Secure Your User's Data (Especially Passwords)?

I've used a different approach to show user confirmation about account creation which is a JavaScript alert but you can easily use header function to redirect user form this page to another page for example login page. I will cover that in my next post.

So, that's it. Combine all the code chunks and you'll have the registration system ready for your website.

amazon

Most Read

#1 How to check if radio button is checked or not using JavaScript? #2 Solution to “TypeError: ‘x’ is not iterable” in Angular 9 #3 How to add Read More Read Less Button using JavaScript? #4 How to uninstall Cocoapods from the Mac OS? #5 PHP Login System using PDO Part 1: Create User Registration Page #6 How to Use SQL MAX() Function with Dates?

Recently Posted

#Jul 22 Is there a CSS parent selector? #Jul 22 Difference between :where and :is in CSS #Jul 22 Does :is() pseudo selector hint at CSS preprocessing in the future? #Jul 22 Control Scrolling with CSS Scroll Snap #Jul 21 Control rendering using CSS content-visibility property #Jul 21 How to use @supports rule in CSS?
You might also like these
What’s a Log File and What are Log File Monitors?MiscellaneousHow to use @each rule with key-value pair in SCSS?SCSSWordPress: How to display slider repeater fields in ACF?WordPressWP_Query Class in WordPressWordPressHow to Remove PHP File Extensions From Your Website URLs?PHPHow to pass arguments in SCSS function?SCSS