HOW TO BUILD A PHP LOGIN FORM USING SESSIONS.

login form

WHAT IS PHP?

PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML.

Nice, but what does that mean? An example:

Example #1 An introductory example<!DOCTYPE html>
<html>
    <head>
        <title>Example</title>
    </head>
    <body>

        <?php
            echo "Hi, I'm a PHP script!";
        ?>

    </body>
</html>

WHAT IS A LOGIN FORM

A Login form is used to enter authentication credentials to access a restricted page or form. The login form contains a field for the username and another for the password. … Like the search form, a login form is basically a record form whose insert, update and delete properties have been disabled

WHAT ARE SESSIONS IN PHP

In general, session refers to a frame of communication between two medium. A PHP session is used to store data on a server rather than the computer of the user. Session identifiers or SID is a unique number which is used to identify every user in a session based environment. The SID is used to link the user with his information on the server like posts, emails etc.

How are sessions better than cookies?

Although cookies are also used for storing user related data, they have serious security issues because cookies are stored on the user’s computer and thus they are open to attackers to easily modify the content of the cookie.Addition of harmful data by the attackers in the cookie may result in the breakdown of the application.
Apart from that cookies affect the performance of a site since cookies send the user data each time the user views a page.Every time the browser requests a URL to the server, all the cookie data for that website is automatically sent to the server within the request.

Below are different steps involved in PHP sessions:
https://540efd8afa5a4c86ea9b44d223b5e0d6.safeframe.googlesyndication.com/safeframe/1-0-38/html/container.html

  • Starting a PHP Session: The first step is to start up a session. After a session is started, session variables can be created to store information. The PHP session_start() function is used to begin a new session.It als creates a new session ID for the user.Below is the PHP code to start a new session:<?php  session_start();  ?>
  • Storing Session Data: Session data in key-value pairs using the $_SESSION[] superglobal array.The stored data can be accessed during lifetime of a session.Below is the PHP code to store a session with two session variables Rollnumber and Name:<?php  session_start();  $_SESSION["Rollnumber"] = "11";$_SESSION["Name"] = "Ajay";  ?>
  • Accessing Session Data: Data stored in sessions can be easily accessed by firstly calling session_start() and then by passing the corresponding key to the $_SESSION associative array.The PHP code to access a session data with two session variables Rollnumber and Name is shown below:<?php  session_start();  echo 'The Name of the student is :' . $_SESSION["Name"] . '<br>'echo 'The Roll number of the student is :' . $_SESSION["Rollnumber"] . '<br>';  ?>Output:The Name of the student is :Ajay The Roll number of the student is :11
  • Destroying Certain Session Data: To delete only a certain session data,the unset feature can be used with the corresponding session variable in the $_SESSION associative array.The PHP code to unset only the “Rollnumber” session variable from the associative session array:<?php  session_start();   if(isset($_SESSION["Name"])){    unset($_SESSION["Rollnumber"]);}  ?>
  • Destroying Complete Session: The session_destroy() function is used to completely destroy a session. The session_destroy() function does not require any argument.<?php  session_start();session_destroy();  ?>

Important Points

  1. The session IDs are randomly generated by the PHP engine .
  2. The session data is stored on the server therefore it doesn’t have to be sent with every browser request.
  3. The session_start() function needs to be called at the beginning of the page, before any output is generated by the script in the browser.

User login interface

Creating a HTML form to login is the first step. It is to get the login details from users.

In this example, it has two fields username and password for user login.

I have specified the validation function and the PHP endpoint with the form tag.

The HTML contains elements to display client-side validation error. Also, it has the code to show a server-side error response based on the login result.

<html>
<head>
<title>User Login</title>
<link href="./view/css/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <div>
        <form action="login-action.php" method="post" id="frmLogin" onSubmit="return validate();">
            <div class="demo-table">

                <div class="form-head">Login</div>
                <?php 
                if(isset($_SESSION["errorMessage"])) {
                ?>
                <div class="error-message"><?php  echo $_SESSION["errorMessage"]; ?></div>
                <?php 
                unset($_SESSION["errorMessage"]);
                } 
                ?>
                <div class="field-column">
                    <div>
                        <label for="username">Username</label><span id="user_info" class="error-info"></span>
                    </div>
                    <div>
                        <input name="user_name" id="user_name" type="text"
                            class="demo-input-box">
                    </div>
                </div>
                <div class="field-column">
                    <div>
                        <label for="password">Password</label><span id="password_info" class="error-info"></span>
                    </div>
                    <div>
                        <input name="password" id="password" type="password"
                            class="demo-input-box">
                    </div>
                </div>
                <div class=field-column>
                    <div>
                        <input type="submit" name="login" value="Login"
                        class="btnLogin"></span>
                    </div>
                </div>
            </div>
        </form>
    </div>
</body>
</html>

and the styles are,

body {
    font-family: Arial;
    color: #333;
    font-size: 0.95em;
}

.form-head {
    color: #191919;
    font-weight: normal;
    font-weight: 400;
    margin: 0;
    text-align: center;
    font-size: 1.8em;
}

.error-message {
    padding: 7px 10px;
    background: #fff1f2;
    border: #ffd5da 1px solid;
    color: #d6001c;
    border-radius: 4px;
    margin: 30px 10px 10px 10px;
}

.demo-table {
    background: #ffffff;
    border-spacing: initial;
    margin: 15px auto;
    word-break: break-word;
    table-layout: auto;
    line-height: 1.8em;
    color: #333;
    border-radius: 4px;
    padding: 30px;
    width: 380px;
    border: 1px solid;
    border-color: #e5e6e9 #dfe0e4 #d0d1d5;
}

.demo-table .label {
    color: #888888;
}

.demo-table .field-column {
    padding: 15px 10px;
}

.demo-input-box {
    padding: 13px;
    border: #CCC 1px solid;
    border-radius: 4px;
    width: 100%;
}

.btnLogin {
    padding: 13px;
    background-color: #5d9cec;
    color: #f5f7fa;
    cursor: pointer;
    border-radius: 4px;
    width: 100%;
    border: #5791da 1px solid;
    font-size: 1.1em;
}

.response-text {
    max-width: 380px;
    font-size: 1.5em;
    text-align: center;
    background: #fff3de;
    padding: 42px;
    border-radius: 3px;
    border: #f5e9d4 1px solid;
    font-family: arial;
    line-height: 34px;
    margin: 15px auto;
}

.terms {
    margin-bottom: 5px;
}

.dashboard {
    background: #d2edd5;
    text-align: center;
    margin: 15px auto;
    line-height: 1.8em;
    color: #333;
    border-radius: 4px;
    padding: 30px;
    max-width: 400px;
    border: #c8e0cb 1px solid;
}
.error-info {
    color: #FF0000;
    margin-left: 10px;
}
a.logout-button {
    color: #09f;
}

Login form validation

This script is for validating the login data at the client-side. If the users submit the login with empty fields then this script will return boolean false.

When it returns false, it displays a validation error message to the users. By returning boolean 0, the form validation script prevents login to proceed further.

    <script>
    function validate() {
        var $valid = true;
        document.getElementById("user_info").innerHTML = "";
        document.getElementById("password_info").innerHTML = "";
        
        var userName = document.getElementById("user_name").value;
        var password = document.getElementById("password").value;
        if(userName == "") 
        {
            document.getElementById("user_info").innerHTML = "required";
        	$valid = false;
        }
        if(password == "") 
        {
        	document.getElementById("password_info").innerHTML = "required";
            $valid = false;
        }
        return $valid;
    }
    </script>

PHP code to process login

The login-action.php file receives and handles the posted login data. It sends the username and password to the processLogin() function.

This method gets the login details and compares with the user database.

It prepares query and binds the login params with it to find the match from the database. If match found the processLogin will return the result.

On successful login, the login-action.php sets the logged-in user session. Otherwise, it will return error by saying “Invalid Credentials”.

<?php
namespace Phppot;

use \Phppot\Member;
if (! empty($_POST["login"])) {
    session_start();
    $username = filter_var($_POST["user_name"], FILTER_SANITIZE_STRING);
    $password = filter_var($_POST["password"], FILTER_SANITIZE_STRING);
    require_once (__DIR__ . "./class/Member.php");
    
    $member = new Member();
    $isLoggedIn = $member->processLogin($username, $password);
    if (! $isLoggedIn) {
        $_SESSION["errorMessage"] = "Invalid Credentials";
    }
    header("Location: ./index.php");
    exit();
}

Get logged-in user profile data to display a welcome message

This code is to display the dashboard after login. The PHP code embedded with this HTML is for getting the user session and the user data from the database.

It displays the welcome message by addressing the user with their display name.

The dashboard contains a logout link in addition to the welcome text.

<?php
namespace Phppot;

use \Phppot\Member;

if (! empty($_SESSION["userId"])) {
    require_once __DIR__ . './../class/Member.php';
    $member = new Member();
    $memberResult = $member->getMemberById($_SESSION["userId"]);
    if(!empty($memberResult[0]["display_name"])) {
        $displayName = ucwords($memberResult[0]["display_name"]);
    } else {
        $displayName = $memberResult[0]["user_name"];
    }
}
?>
<html>
<head>
<title>User Login</title>
<link href="./view/css/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <div>
        <div class="dashboard">
            <div class="member-dashboard">Welcome <b><?php echo $displayName; ?></b>, You have successfully logged in!<br>
                Click to <a href="./logout.php" class="logout-button">Logout</a>
            </div>
        </div>
    </div>
</body>
</html>

Member.php

This is the PHP class created in this example to handle the login process. The getMemberById method request DataSource to fetch the member results.

<?php
namespace Phppot;

use \Phppot\DataSource;

class Member
{

    private $dbConn;

    private $ds;

    function __construct()
    {
        require_once "DataSource.php";
        $this->ds = new DataSource();
    }

    function getMemberById($memberId)
    {
        $query = "select * FROM registered_users WHERE id = ?";
        $paramType = "i";
        $paramArray = array($memberId);
        $memberResult = $this->ds->select($query, $paramType, $paramArray);
        
        return $memberResult;
    }
    
    public function processLogin($username, $password) {
        $passwordHash = md5($password);
        $query = "select * FROM registered_users WHERE user_name = ? AND password = ?";
        $paramType = "ss";
        $paramArray = array($username, $passwordHash);
        $memberResult = $this->ds->select($query, $paramType, $paramArray);
        if(!empty($memberResult)) {
            $_SESSION["userId"] = $memberResult[0]["id"];
            return true;
        }
    }
}

Redirect users to Login or Dashboard based on Session

A landing page index.php contains code to check logged-in session and route users accordingly. The following code shows how to redirect users based on the session.

<?php
session_start();
if(!empty($_SESSION["userId"])) {
    require_once './view/dashboard.php';
} else {
    require_once './view/login-form.php';
}
?>

Handling logout in PHP

By clicking the logout link from the dashboard, it calls this PHP script. In this script, it clears the current login session and redirects users back to the login. The logout code is,

<?php 
session_start();
$_SESSION["user_id"] = "";
session_destroy();
header("Location: index.php");

DataSource.php

This class establishes a connection object to access the database based on the request. It has the select function to prepare a fetch query to return the results.

<?php
namespace Phppot;

/**
 * Generic datasource class for handling DB operations.
 * Uses MySqli and PreparedStatements.
 *
 * @version 2.3
 */
class DataSource
{

    // PHP 7.1.0 visibility modifiers are allowed for class constants.
    // when using above 7.1.0, declare the below constants as private
    const HOST = 'localhost';

    const USERNAME = 'root';

    const PASSWORD = '';

    const DATABASENAME = 'phpsamples';

    private $conn;

    /**
     * PHP implicitly takes care of cleanup for default connection types.
     * So no need to worry about closing the connection.
     *
     * Singletons not required in PHP as there is no
     * concept of shared memory.
     * Every object lives only for a request.
     *
     * Keeping things simple and that works!
     */
    function __construct()
    {
        $this->conn = $this->getConnection();
    }

    /**
     * If connection object is needed use this method and get access to it.
     * Otherwise, use the below methods for insert / update / etc.
     *
     * @return \mysqli
     */
    public function getConnection()
    {
        $conn = new \mysqli(self::HOST, self::USERNAME, self::PASSWORD, self::DATABASENAME);
        
        if (mysqli_connect_errno()) {
            trigger_error("Problem with connecting to database.");
        }
        
        $conn->set_charset("utf8");
        return $conn;
    }

    /**
     * To get database results
     * @param string $query
     * @param string $paramType
     * @param array $paramArray
     * @return array
     */
    public function select($query, $paramType="", $paramArray=array())
    {
        $stmt = $this->conn->prepare($query);
        
        if(!empty($paramType) && !empty($paramArray)) {
            $this->bindQueryParams($stmt, $paramType, $paramArray);
        }
        
        $stmt->execute();
        $result = $stmt->get_result();
        
        if ($result->num_rows > 0) {
            while ($row = $result->fetch_assoc()) {
                $resultset[] = $row;
            }
        }
        
        if (! empty($resultset)) {
            return $resultset;
        }
    }
    
    /**
     * To insert
     * @param string $query
     * @param string $paramType
     * @param array $paramArray
     * @return int
     */
    public function insert($query, $paramType, $paramArray)
    {
        print $query;
        $stmt = $this->conn->prepare($query);
        $this->bindQueryParams($stmt, $paramType, $paramArray);
        $stmt->execute();
        $insertId = $stmt->insert_id;
        return $insertId;
    }
    
    /**
     * To execute query
     * @param string $query
     * @param string $paramType
     * @param array $paramArray
     */
    public function execute($query, $paramType="", $paramArray=array())
    {
        $stmt = $this->conn->prepare($query);
        
        if(!empty($paramType) && !empty($paramArray)) {
            $this->bindQueryParams($stmt, $paramType="", $paramArray=array());
        }
        $stmt->execute();
    }
    
    /**
     * 1. Prepares parameter binding
     * 2. Bind prameters to the sql statement
     * @param string $stmt
     * @param string $paramType
     * @param array $paramArray
     */
    public function bindQueryParams($stmt, $paramType, $paramArray=array())
    {
        $paramValueReference[] = & $paramType;
        for ($i = 0; $i < count($paramArray); $i ++) {
            $paramValueReference[] = & $paramArray[$i];
        }
        call_user_func_array(array(
            $stmt,
            'bind_param'
        ), $paramValueReference);
    }
    
    /**
     * To get database results
     * @param string $query
     * @param string $paramType
     * @param array $paramArray
     * @return array
     */
    public function numRows($query, $paramType="", $paramArray=array())
    {
        $stmt = $this->conn->prepare($query);
        
        if(!empty($paramType) && !empty($paramArray)) {
            $this->bindQueryParams($stmt, $paramType, $paramArray);
        }
        
        $stmt->execute();
        $stmt->store_result();
        $recordCount = $stmt->num_rows;
        return $recordCount;
    }
}

Database script

This script contains the CREATE statement for the registered_users table. Also, it has the data dump to check the example with test login details.

--
-- Table structure for table `registered_users`
--

CREATE TABLE `registered_users` (
  `id` int(8) NOT NULL,
  `user_name` varchar(255) NOT NULL,
  `display_name` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `registered_users`
--

INSERT INTO `registered_users` (`id`, `user_name`, `display_name`, `password`, `email`) VALUES
(1, 'kate_91', 'Kate Winslet', 'ad5611358209efdc202d35127a160748', 'kate@wince.com');

--
-- Indexes for table `registered_users`
--
ALTER TABLE `registered_users`
  ADD PRIMARY KEY (`id`);


--
-- AUTO_INCREMENT for table `registered_users`
--
ALTER TABLE `registered_users`
  MODIFY `id` int(8) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
COMMIT;

Test login details

After setting this example code and database in your computer, use the following test data to check the example login system.

Username: kate_91
Password: kate@03

PHP login script with session output

This output screenshot shows the login form interface. It has the input fields to get the user login details.

User Login Form Screenshot

This is the screenshot of the welcome message. Once logged-in, then the user will see this response in the browser.

This view will show a welcome message by addressing the logged-in user. It also has a link to logout as shown below.

User Dashboard Output

Drop your comment

0Shares

Related Post

Leave a Reply

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