PHP Login Registration Form with AJax - Part 1

Skill Level: Intermediate 

This is Part 1 of 4 of this series. Part 2 will be launched soon!

Grab your Red Bull, Rockstar or espresso for this one as this is going to be an in depth project. We will be using jQuery, PHP, MySql, Ajax along with the Active Record pattern to create the foundation that can be scaled into something much larger if you wish. This login and registration form will have the ability to toggle back and forth from the login form to the registration form. I'll also show you how to return error messages with JSON as well as our success messages, all while using OOP.  We will also be implementing real world security features such as using PDO for our database connection and taking advantage of the built in prepared statement functionality. 

 

A Glance at the Project

A login form is a necessity to many web applications. There are tons of ways to create one, good and bad. I've seen lots of great ones and lots of not so great ones. It acts as a direct entry point into your web app. It needs to be secure. It needs to be functional. It needs to have an appeal to your users. It's something that is so common that it can be somewhat taken for granted. When creating a login form, we need to make sure that a couple of things happen. We need to secure our app, and we need to secure our users information. 

This is another project that I will create in vanilla JavaScript in the future, but for now, we will be creating the login form using the jQuery API.

Ajax provides powerful functionality to allow us to create dynamic login forms without a page refresh. This gives our users a much better experience.

 

What We're Building

  • Build a styled and user friendly form using Bootstrap
  • Process our form without page refresh using Ajax
  • Server side validation using PHP
  • Display error messages that get parsed with JSON
  • Show icon and text while our form is processing
  • Show success message once our form has submitted successfully

 

Hosting / Localhost

If you're setting up hosting, I highly recommend InMotion Hosting. They have been the best over the years. You can get a special deal signing up directly through me. Get the best hosting now!

If your using your localhost on your computer, you can install Xampp and run your local apache server. If you need to download xampp, you can do so here https://www.apachefriends.org/index.html. Make sure to download the version for your system with the latest PHP version. You can use whichever code editor you like. I personally will be using Brackets. 

 

Files we Need to Create

Go ahead and create all of these files now on your hosting server or local server inside a folder called login_tutorial.

 

  • index.php 
  • style.css - Main CSS Stylesheet
  • scripts.js - Main JavaScript Page
  • db.php - This will store our database credentials
  • functions.php - Any custom functions we create will go in here
  • login.php - This is going to act as our controller when we send our Ajax request
  • DbObject.php - Our main Database class. This will handle our active record functions
  • User.php - our user class that will extend our DbObject class

 

Ok ok, I know this looks like a lot. You're right, it is. However, I want to demonstrate a way on how to create re-usable code and make it more modular. Remember the DRY principles. Do not repeat yourself! Repeating yourself in your code is not ideal if you can help it.  This is going to prevent that and we can use this system and expand it into other projects. 

Got your coffee, energy drink or beer? I'll be sipping on a local brew myself. Let's dive in!

Now that you have created that list of files, we need to get some code in them. On our index.php page, we need to include our db.php and login.php pages at the top of the page. Create an HTML skeleton and in our head tag, we need to link to the bootstrap API so our layout will function properly. Our login form is going to be able to toggle from a registration form to a login form and so forth so we need to add TWO forms to our markup.

 

<?php 
 include "db.php";
include "login.php";

?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login with PHP and Ajax</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <link rel="stylesheet" href="/style.css" type="text/css">
</head>

<body>
   
<div class="container" id="formContainer">
   <div class="row">
       <div class="col-sm-12 col-md-6 col-lg-6" id="form">

<!--LOGIN FORM-------------------------->          
           <form method="post" action="" id="loginForm">
               <div id="imgContainer">
                   <img src="/login-img.png">
                   <h2>Login</h2>
               </div>

               <div class="container">
                  <div id="loginMsgs"></div>

                      <div class="form-group">
                          <label for="username">Username</label>
                          <div id="error_username"></div>
                          <input type="text" class="form-control" name="user[username]">
                       </div>


                      <div class="form-group">
                          <label for="username">Password</label>
                          <div id="error_password"></div>
                          <input type="password" class="form-control" name="user[password]">
                      </div>

                      <div class="form-group">
                          <button class="btn btn-primary" id="submit">Login</button>   
                      </div>

               </div>

           </form>
           
           
    <!--REGISTRATION FORM---------------------->

           <form method="post" action="" id="registerForm">
               <div id="imgContainer">
                   <img src="/login-img.png">
                   <h4>Let 's get your account setup</h4>
               </div>

               <div class="container">
                  
                   <div id="loading" class="alert alert-info alert-dismissable hide"> 
                       <a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
                   </div>
                     
                        
                      <div class="form-group">
                          <label for="name">Name</label>
                          <div id="error_name"></div>
                          <input type="text" class="form-control" name="register[name]" placeholder="Enter your full name">
                      </div>
                       
                      <div class="form-group">
                          <label for="email">Email</label>
                          <div id="error_email"></div>
                          <input type="email" class="form-control" name="register[email]" placeholder="Enter your email">
                      </div>
                       
                       
                      <div class="form-group">
                          <label for="username">Username</label>
                          <div id="error_username"></div>
                          <input type="text" class="form-control" name="register[username]" placeholder="Create your username">
                       </div>


                      <div class="form-group">
                          <label for="username">Password</label>
                          <div id="error_password"></div>
                          <input type="password" class="form-control" name="register[password]" placeholder="Create a password">
                      </div>

                      <div class="form-group">
                          <button class="btn btn-primary" id="register">Register Now!</button>   
                      </div> 
                 </div>  
           </form>
           
           <div id="registerBtnContainer">
                <p>No account? Sign up for free!</p>
                <span><button id="registerBtn" class="btn btn-outline-primary">Register</button></span>
           </div>
           
           <div id="loginBtnContainer">
                <p>Already signed up? Login now</p>
               <span><button id="loginBtn" class="btn btn-outline-primary">Login</button></span>
           </div>
           <div>
                <span>Forgot Username?</span> <span>Forgot Password?</span>
           </div>
           <br />
       </div>
   </div>
</div>
   
    
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="/scripts.js" type="text/javascript"></script>

</body>
</html>

 

Add Our CSS

That is our basic markup to create our forms and our container. We created a container with the ID of #formContainer, a form wrapper with an ID of #form, a login form with the ID of #loginForm and a registration form with the ID of #registerForm.  We will be using these Id's when we start writing our JavaScript. Notice also in our forms the `name` attribute on our input fields. Instead of create name="username", we are setting it name="register[username]".  This is a very useful feature of HTML 5 that allows us to store our data into a custom array. In this case, our data will be stored in an array called `register`.  This will come in handy later.

Before we dive into any logic, our forms look pretty haggard, and we certainly don't need two of them showing up right now, so let's fix that. 

We need to hide our registration form for the time being, center our form and add a background. We are going to add a background color and a box shadow to our #form  and set text-align:center. We're also going to add a sweet looking background image to our body and make our form look badass!

 

/* SET OUR WIDTH AND HIGHT TO 100% FOR HTML AND BODY */
html,
body {
    width:100%;
    height:100%;
}

/* SET BACKGROUND TO OUR IMAGE. */
body {
    background-image: url(bg.jpeg);
    background-size: cover;
    background-repeat: no-repeat;
    background-attachment:fixed;
}

/* SET BACKGROUND TO OUR FORM WITH A DROP SHADOW AND SET OUR COLOR TO WHITE OUR BACKGROUND USES AN ALPHA CHANNEL HEX CODE TO GIVE US OPACITY.*/
#form {
    background:#18184c73; /* CAN ALSO USE RGBA. EXAMPLE: background: rgba(24, 24, 76, .45);
    box-shadow:0px 5px 23px 0px #eae3e3;
    color:#fff;
   
}

#formContainer {
    margin-top:100px;
    text-align: center;
}

 

Looking better, but let's make our buttons full width and size up our image a bit. The image size we set may vary depending on your image. Let's also add some styling to our input fields. Lets give it an opacity effect as well, remove the border, give it a slight border radius and make sure the color is set to white. We need to use the !important to make sure these values are overwritten since they are already defined in our bootstrap files. 

 

img {
    width: 50%;
    margin-top:20px;
    margin-bottom: 20px;
}

.btn {
    width:100%;
    margin-bottom:50px;
}

input {
    background:#ffffff61 !important;
    border:none !important;
    border-radius:5px;
    color:#fff;
}

input[name^="register"]::placeholder { /* Selects placeholders of inputs with the name attribute that begins with 'register'. */
    color:#fff;
    opacity:0.6;
}

I mentioned above that we were adding some opacity to our inputs. We did that with the alpha channel. Don't let the opacity confuse you with the CSS opacity attribute. The opacity will set a global transparency to the entire element we're targeting, so in this case if we used opacity on our inputs, it would also add opacity to our text too. We don't want that!

Now, we still have both forms showing up. We need to have our registration form be hidden on page load, and when we click a button, we need to toggle our display properties so our registration form will show, and our login form will be hidden.  I also added a media query to target tablet and desktop sizes to add some margin to our form. This will center it on our page.

#loginBtnContainer, // This is the div element that holds our button to toggle forms */
#registerForm { /* This is our Registration form. It needs to be hidden by default */
    display:none;
}

.hide {
    display:none !important;
}

.show {
    display:block !important;
}
@media only screen and (max-width:575px) {
    #form {
        margin:0 15px; /* Gives us some left and right margin on smaller screens */
    }
}

@media only screen and (min-width:768px) {
    #form {
        margin-left:100px auto; /* Set our margin on top and bottom to 100px and set our margin left and right to auto; */
    }
}

 

Adding Our jQuery

Walla! We now have our responsive forms. We need to add our logic, however. We have a fancy form, but it does nothing. Let's bring in the heavy hitter and introduce our JQuery. This will give our form the ability to change CSS and submit our data to our PHP.

Let's start by creating some variables in our scripts.js

var showRegisterFormCont = $("#registerBtnContainer"); // Registration form button container
var showRegisterFormBtn = $("#registerBtn")      // Registration button 
var showLoginFormCont = $("#loginBtnContainer"); // Login form button container
var showLoginFormBtn = $("#loginBtn")            // Login button 
var loginForm = $("#loginForm");                 // Login Form
var registerForm = $("#registerForm");           // Registration Form
var loginBtn = $("#submit");                     // Login Submit Button
let registerBtn = $("#register");                // Register Submit Button
var loading = $("#loading");                     // Loading Data Div for Registration
var loginMsgs= $("#loginMsgs");                  // Div to hold our messages for login

 

Now that we have these variables, we need to be able to toggle between our two forms. When we click on $(showRegisterFormBtn), we want it to hide the login form and show the registration form. When we click on $(showLoginFormBtn), we want it to do just the opposite. We can accomplish this several ways. We can create one button that toggles between both forms and we can use the JQuery toggle() function. We could also add and remove classes each time a button a clicked to show the new content based on which class is active. In this case, since we already set our registration form and login button container to display:none, lets use the css() function and change the display properties on our forms and buttons.

 

$(showRegisterFormBtn).click(function() {
    
    $(loginForm).css('display', 'none');
    $(registerForm).css('display', 'block');
    $(showLoginFormCont).css('display', 'block');
    $(showRegisterFormCont).css('display', 'none');
})

$(showLoginFormBtn).click(function() {
    
    $(loginForm).css('display', 'block');
    $(registerForm).css('display', 'none');
    $(showLoginFormCont).css('display', 'none');
    $(showRegisterFormCont).css('display', 'block');
})

 

Now our forms should be toggling between display properties. Pretty cool! What about sending our data though? Our login portion of this will be on part 2 of this series, so first, we need to take care of sending our users data to the database when they register.

 

What we Need to Achieve

  • Add click event to our registration submit button
  • Create JSON array that holds our form data so we can pass it to our Ajax
  • Create Ajax request that sends our data to our login.php page
  • Create a new array on login.php with our new form data and send the array to our User class where it will be parsed and sent to the database

 

Let's add our click event to our registration submit button and make sure it works by using an alert();

$(registerBtn).click(function(e) {
      e.preventDefault();
      alert();
};

 

The `e` that we passed as an argument in our function stands for "event". It's common to see "event", "e" or "evt". It doesn't really matter what you pass in there, but there are some standards that are nice to follow by. 

We then attach the preventDefault() to our event which removes the default functionality of the button, preventing it from being submitted. Our page should have displayed a blank alert without a page refresh. If it worked for you, go ahead and remove the alert() and let's create our formData variable with our JSON data and put it under our e.preventDefault();

var formData = {
      
     "name" : $('input[name="register[name]"]').val(),
     "email" : $('input[name="register[email]"]').val(),
     "username" : $('input[name="register[username]"]').val(),
     "password" : $('input[name="register[password]"]').val()
                            
};

 

If we send our formData to the console, this is what our output will look like. We can grab this info easily with PHP.

 

{name: "Richard", email: "richard@thecodecrypt .com", username: "codecrypt", password: "test"};

 

Next, we need to create our Ajax request. Since we are sending data, we need to set it to POST and we're going to send our form data to login.php.  Along with our form data, we're also going to send an `action` in our data. This action can help us determine which Ajax request will be coming in. You can give the action whatever name you would like, but since this ajax request pertains to our registration, we are going to call it 'register'.  We will also add the beforeSend function at the end of the Ajax which will hold some jQuery that will show our loading div and show some text while the form is processing.

 

.ajax({
        
        type:'post',
        url:'login.php',
        data:{action: 'register', formData:formData},
        beforeSend:  function() {

                $(loading).removeClass("hide").addClass("show");
                $(loading).html("<h5>Creating Account...</h5>");
        
        },
        
    })

Now we need to add our callback to the end of our ajax.  Here we will introduce the .done() callback. The .done() function is part of the jQuery Deferred Object. Essentially, the .done() will be called once the deferred object is resolved. If there is an error, the .done() will fail. 

 

    .done(function(data) {   //Callback once our Ajax in complete
        console.log(data)    //Send our data to the console
        setTimeout(function() {  //Set a Timeout wrapper around to run after 2 seconds.
            
            $(loading).removeClass("alert-info").addClass("alert-success");
            $(loading).html("<h5>Success!</h5>");
            $(loading).fadeOut(2000);
                      
                setTimeout(function() {
                      $(loading).removeClass("show").addClass("hide");
                }, 2000);

        }, 2000);

         $(registerForm)[0].reset();  //Reset our form after submission
    
    });

 

In your login.php, we need to check to make sure our formData isset and check our output to make sure our ajax is working properly. We will do a simple print_r($data) to display our data to the console. You should get an array with some key/value pairs.

 

<?php

if(isset($_POST['formData']) && isset($_POST['action'])) {
    
    $data = $_POST['formData'];
    $action = $_POST['action'];
    
    if($action == "register") {
        
        print_r($data);
       
    } 
}

?>

 

If you got the key/value pairs to show up in the console, congratulations! You've completed Part 1 of this series! In the next part, we will cover the PHP side of our registration form. We will creating our active record pattern to help us create reusable, modular and clean code. If for any reason something in this first part does not make sense or isn't working for your, please review the code before moving forward. Make sure you understand what we have achieved so far. If something absolutely does not make sense, feel free to leave a comment and I would love to help out! 

See you in the next section!

Comments (6)

Rated 5 out of 5 based on 2 voters
This comment was minimized by the moderator on the site

Greate job.

Ermias
This comment was minimized by the moderator on the site

Thanks! Hope it helped!

Richard H.
This comment was minimized by the moderator on the site

SyntaxError: expected expression, got '.' scripts.js:45

bootsmann
This comment was minimized by the moderator on the site

because i messed around ;-(
thanks for sharing your knowledge. more please.

bootsmann
This comment was minimized by the moderator on the site

Did you get that syntax error figured out? Move on to part 2 if you finished with part 1! I'll release a part 3 soon which will have the login and error functionality!

Richard H.
This comment was minimized by the moderator on the site

For those who wish to experience many reasons, it seems to be so called. Submitted so many sides, Wiki page writers and know what we can do if it’s interesting, more and more people like to come and join.

Richard Lopez
There are no comments posted here yet

Leave your comments

  1. Posting comment as a guest. Sign up or login to your account.
Rate this post:
Attachments (0 / 3)
Share Your Location
© 2019 The Code Crypt. All Rights Reserved.