How To Make PHP Login and Sign-Up System

In this step-by-step tutorial guide you will learn how to create a session based user login and Sign-Up system using PHP with MySQL Database.

Create PHP Login & Sign-Up System

Here we will use MySQLi Procedural to build this login system. But don’t worry, at the end I will provide the same code in MySQLi OOP and PDO. Let’s start –

Step 1: Database Setup

  • Database name: php_login
  • Table name: users
  • “users” table column:
    • id
    • name
    • email
    • password

Use the following SQL code to create the users table and its column.

CREATE TABLE `users` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(30) NOT NULL,
    `email` varchar(30) NOT NULL,
    `password` varchar(150) NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `email` (`email`)
) ENGINE = InnoDB AUTO_INCREMENT = 12 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci;
MySQL users table structure for PHP login and registration system

Step 2: Create the Project Folder

Open your xampp htdocs folder or your localhost www directory and create a folder called php-login-registration. This is our project folder.

Step 3: Create PHP Files for this Project

Now in the project folder we need to create the following PHP files –

PHP login application folder structure

Step 4: “db_connection.php” for Database Connection

Change the database details according to yours –

<?php
$db_host = 'localhost';
$db_user = 'root';
$db_password = '';
$db_name = 'php_login';

$conn = mysqli_connect($db_host, $db_user, $db_password, $db_name);

// CHECKING THE DATABASE CONNECTION
if(mysqli_connect_errno()){
    echo "Connection Failed - ".mysqli_connect_error();
    exit;
}

Step 5: Write Code for User Signup

To sign-up a new user we need to create the on_register.php and register.php.

on_register.php contains the on_register() function which has the code for inserting new users. The on_register() function will be called when the sign up form (which is in the register.php) is submitted.

1. “on_register.php” Handles User Signing Up

<?php
/**
 * Handles user registration.
 * 
 * @param mysqli $conn The database connection object.
 * @return array Registration result.
 */
function on_register($conn)
{
    // Sanitize and retrieve form data
    $name = htmlspecialchars(trim($_POST['name']));
    $email = trim($_POST['email']);
    $pass = trim($_POST['password']);

    // Check for empty fields
    if (empty($name) || empty($email) || empty($pass)) {
        $arr = [];
        if (empty($name)) $arr["name"] = "Must not be empty.";
        if (empty($email)) $arr["email"] = "Must not be empty.";
        if (empty($pass)) $arr["password"] = "Must not be empty.";
        return [
            "ok" => 0,
            "field_error" => $arr
        ];
    }

    // Validate email format
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        return [
            "ok" => 0,
            "field_error" => [
                "email" => "Invalid email address."
            ]
        ];
    }

    // Check password length
    if(strlen($pass) < 4){
        return [
            "ok" => 0,
            "field_error" => [
                "password" => "Must be at least 4 characters."
            ]
        ];
    }

    // Check if email is already registered
    $sql = "SELECT `email` FROM `users` WHERE `email` = ?";
    $stmt = mysqli_prepare($conn, $sql);
    mysqli_stmt_bind_param($stmt, "s", $email);
    mysqli_stmt_execute($stmt);
    mysqli_stmt_store_result($stmt);
    if(mysqli_stmt_num_rows($stmt) !== 0){
        return [
            "ok" => 0,
            "field_error" => [
                "email" => "This Email is already registered."
            ]
        ];
    }

    // Hash password
    $pass = password_hash($pass, PASSWORD_DEFAULT);

    // Insert user into database
    $sql = "INSERT INTO `users` (`name`, `email`, `password`) VALUES (?,?,?)";
    $stmt = mysqli_prepare($conn, $sql);
    mysqli_stmt_bind_param($stmt, "sss", $name,$email,$pass);
    $is_inserted = mysqli_stmt_execute($stmt);
    if($is_inserted){
        return [
            "ok" => 1,
            "msg" => "You have been registered successfully.",
            "form_reset" => true
        ];
    }
    // Return error message if insertion failed
    return [
        "ok" => 0,
        "msg" => "Something went wrong!"
    ];
}

2. “register.php” User can Signup

<?php
session_start();

// Redirect if user is already logged in
if(isset($_SESSION['logged_user_id'])){
    header('Location: home.php');
    exit;
}

// Handle form submission
if ($_SERVER["REQUEST_METHOD"] === "POST") {
    require_once __DIR__ . "/db_connection.php";
    require_once __DIR__."/on_register.php";

    // Check if necessary fields are set
    if (
        isset($conn) &&
        isset($_POST["name"]) &&
        isset($_POST["email"]) &&
        isset($_POST["password"])
    ) {
        $result = on_register($conn);
    }
}

// Determine if post values should be shown
$show = isset($result["form_reset"]) ? true : false;

// Function to echo post value and prevent XSS
function post_value($field){
    global $show;
    if(isset($_POST[$field]) && !$show){
        echo 'value="'.trim(htmlspecialchars($_POST[$field])).'"';
        return;
    }    
}
?>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sign Up</title>
    <link rel="stylesheet" href="./style.css">
</head>

<body>
    <div class="container">
        <h1>Sign Up</h1>
        <form action="" method="POST" id="theForm">
            <label for="user_name">Name: <span></span></label>
            <input type="text" class="input" name="name" <?php post_value("name"); ?> id="user_name" placeholder="Your name">

            <label for="user_email">Email: <span></span></label>
            <input type="email" class="input" name="email" <?php post_value("email"); ?> id="user_email" placeholder="Your email">

            <label for="user_pass">Password: <span></span></label>
            <input type="password" class="input" name="password" <?php post_value("password"); ?> id="user_pass" placeholder="New password">
            
            <!-- Display registration message -->
            <?php if(isset($result["msg"])){ ?>
                <p class="msg<?php if($result["ok"] === 0){ echo " error"; } ?>"><?php echo $result["msg"]; ?></p>
            <?php } ?>
            
            <input type="submit" value="Sign Up">
            <div class="link"><a href="./login.php">Login</a></div>
        </form>
    </div>
    
    <!-- JavaScript to display field errors -->
    <?php if(isset($result["field_error"])){ ?>
        <script>
            let field_error = <?php echo json_encode($result["field_error"]); ?>;
            let el = null;
            let msg_el = null;
            for(let i in field_error){
                el = document.querySelector(`input[name="${i}"]`);
                el.classList.add("error");
                msg_el = document.querySelector(`label[for="${el.getAttribute("id")}"] span`);
                msg_el.innerText = field_error[i];
            }
        </script>
    <?php } ?>
</body>
</html>

Step 6: Write Code for User Login

Similar to the user registration the on_login.php contain the code to login for existing users. The on_login() function will be called on submission of the login form which is in the login.php.

1. “on_login.php” Handles user login

<?php
/**
 * Handles user login.
 * 
 * @param mysqli $conn The database connection object.
 * @return array Login result.
 */
function on_login($conn){
    // Retrieve and sanitize form data
    $email = trim($_POST['email']);
    $pass = trim($_POST['password']);
    
    // Check for empty fields
    if (empty($email) || empty($pass)) {
        $arr = [];
        if (empty($email)) $arr["email"] = "Must not be empty.";
        if (empty($pass)) $arr["password"] = "Must not be empty.";
        return [
            "ok" => 0,
            "field_error" => $arr
        ];
    }
    
    // Validate email format
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        return [
            "ok" => 0,
            "field_error" => [
                "email" => "Invalid email address."
            ]
        ];
    }

    // Find user by email
    $sql = "SELECT * FROM `users` WHERE `email` = ?";
    $stmt = mysqli_prepare($conn, $sql);
    mysqli_stmt_bind_param($stmt, "s", $email);
    mysqli_stmt_execute($stmt);
    $data = mysqli_stmt_get_result($stmt);
    $row = mysqli_fetch_array($data, MYSQLI_ASSOC);

    // If user doesn't exist
    if($row === NULL){
        return [
            "ok" => 0,
            "field_error" => [
                "email" => "This email is not registered."
            ]
        ];
    }

    // Verify user password
    $password_check = password_verify($pass, $row["password"]);
    if($password_check === false){
        return [
            "ok" => 0,
            "field_error" => [
                "password" => "Incorrect Password."
            ]
        ];
    }

    // Set user id to session and redirect to home page
    $_SESSION['logged_user_id'] = $row["id"];  
    header('Location: home.php');
    exit;
}

2. “login.php” User can Login

<?php
/**
 * Start session to manage user login state.
 */
session_start();

// Redirect if user is already logged in
if (isset($_SESSION['logged_user_id'])) {
    header('Location: home.php');
    exit;
}

// Handle form submission
if ($_SERVER["REQUEST_METHOD"] === "POST") :
    require_once __DIR__ . "/db_connection.php";
    require_once __DIR__ . "/on_login.php";

    // Check if necessary fields are set
    if (isset($conn) && isset($_POST["email"]) && isset($_POST["password"])) {
        $result = on_login($conn);
    }
endif;

/**
 * Echoes post value securely to prevent XSS attacks.
 *
 * @param string $field The field name.
 * @return void
 */
function post_value($field)
{
    if (isset($_POST[$field])) {
        echo 'value="' . trim(htmlspecialchars($_POST[$field])) . '"';
        return;
    }
}
?>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login Page</title>
    <link rel="stylesheet" href="./style.css">
</head>

<body>
    <div class="container">
        <h1>Login</h1>
        <form action="" method="POST">
            <label for="user_email">Email: <span></span></label>
            <input type="email" class="input" name="email" <?php post_value("email"); ?> id="user_email" placeholder="Your email">

            <label for="user_pass">Password: <span></span></label>
            <input type="password" class="input" name="password" <?php post_value("password"); ?> id="user_pass" placeholder="Your password">

            <input type="submit" value="Login">
            <div class="link"><a href="./register.php">Sign Up</a></div>
        </form>
    </div>
    <?php
    // JavaScript to display field errors
    if (isset($result["field_error"])) { ?>
        <script>
            let field_error = <?php echo json_encode($result["field_error"]); ?>;
            let el = null;
            let msg_el = null;
            for (let i in field_error) {
                el = document.querySelector(`input[name="${i}"]`);
                el.classList.add("error");
                msg_el = document.querySelector(`label[for="${el.getAttribute("id")}"] span`);
                msg_el.innerText = field_error[i];
            }
        </script>
    <?php } ?>
</body>
</html>

Step 7: After a User Logs in Successfully

After login successfully, the user will be redirected to the home.php and the get_user.php will fetch the user information from the database.

1. “get_user.php” Fetch User Data by User ID

<?php
/**
 * Retrieves user data from the database by user ID.
 * 
 * @param mysqli $conn The database connection object.
 * @param int $id The user ID.
 * @return array|false User data if found, otherwise false.
 */
function get_user($conn, $id){
    // Validate user ID
    if(!filter_var($id, FILTER_VALIDATE_INT)){
        return false;
    }
    
    // Query to select user by ID
    $sql = "SELECT * FROM `users` WHERE `id` = ?";
    $stmt = mysqli_prepare($conn, $sql);
    mysqli_stmt_bind_param($stmt, "i", $id);
    mysqli_stmt_execute($stmt);
    
    // Fetch user data
    $data = mysqli_stmt_get_result($stmt);
    $row = mysqli_fetch_array($data, MYSQLI_ASSOC);

    // Return user data if found, otherwise false
    if($row === NULL) return false;
    return $row;
}

2. “home.php” Home Page for Logged In User

<?php
/**
 * Start session and regenerate session ID for security.
 */
session_start();
session_regenerate_id(true);

// Redirect to logout page if user session is invalid
if (!isset($_SESSION['logged_user_id']) || empty($_SESSION['logged_user_id']) || !is_numeric($_SESSION['logged_user_id'])) {
    header('Location: logout.php');
    exit;
}

// Include necessary files
require_once __DIR__ . "/db_connection.php";
require_once __DIR__ . "/get_user.php";

// Get user data from the database based on session ID
$user = get_user($conn, $_SESSION['logged_user_id']);

// Redirect to logout page if user data is not found
if ($user === false) {
    header('Location: logout.php');
    exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Home</title>
    <link rel="stylesheet" href="./style.css">
</head>
<body>
    <div class="container">
        <div class="profile">
            <!-- Display user profile information -->
            <img src="https://robohash.org/set_set3/<?php echo $user["id"]; ?>?size=200x200" alt="<?php echo $user["name"]; ?>">
            <h2><?php echo $user["name"]; ?><span><?php echo $user["email"]; ?></span></h2>
            <a href="./logout.php">Log out</a>
        </div>
    </div>
</body>
</html>

Step 8: “logout.php” Logout the Logged In User

<?php
/**
 * Start the session.
 */
session_start();

// Unset all session variables
$_SESSION = array();

// If session cookies are used, delete the session cookie
if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
}

// Destroy the session
session_destroy();

// Redirect to the login page
header("Location: login.php");
exit;

Step 9: Stylesheet for this Application “style.css”

Here is the CSS for this application user-interface:

@import url("https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;700&display=swap");
*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
    font-size: 16px;
}

body {
    background-color: #f7f7f7;
    font-family: "Ubuntu", sans-serif;
    margin: 0;
    padding: 0;
    color: #222222;
    overflow-x: hidden;
    overflow-wrap: break-word;
    -moz-osx-font-smoothing: grayscale;
    -webkit-font-smoothing: antialiased;
    padding: 50px;
}

.container {
    background-color: white;
    border-radius: 3px;
    box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175);
    margin: 0 auto;
    max-width: 450px;
    padding: 40px;
}

.container h1 {
    margin: 0 0 40px 0;
    text-align: center;
}

input,
button {
    font-family: "Ubuntu", sans-serif;
    font-size: 1rem;
    outline: none;
}

.input {
    padding: 15px;
    width: 100%;
    margin-bottom: 15px;
    border: 1px solid #bbbbbb;
    border-radius: 3px;
}

.input:hover {
    border-color: #999999;
}

.input:focus {
    border-color: #0d6efd;
}

.input.error {
    border-color: red !important;
}
label span {
    color: red;
}

.msg {
    border: 1px solid #66ba7a;
    background: #f3ffd1;
    padding: 10px;
    border-radius: 3px;
}
.msg.error {
    border-color: #e33b54;
    background: #f9d7dc;
}

[type="submit"] {
    background: #0d6efd;
    color: white;
    border: 1px solid rgba(0, 0, 0, 0.175);
    border-radius: 3px;
    padding: 12px 0;
    cursor: pointer;
    box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
    margin-top: 5px;
    font-weight: bold;
    width: 100%;
}

[type="submit"]:hover {
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}

label {
    font-weight: bold;
    display: inline-block;
    margin-bottom: 3px;
}

.link {
    margin-top: 20px;
    text-align: center;
}

.link a {
    color: #0d6efd;
}

.profile {
    text-align: center;
}
.profile img {
    display: inline-block;
    border: 3px solid #ccc;
    border-radius: 50%;
    width: 150px;
    height: 150px;
}

h2 span {
    display: block;
    font-size: 15px;
    font-weight: 400;
    color: #888;
}

Step 10: Testing

Testing the PHP login and registration system

PHP Login & Registration System with MySQLi OOP and PDO

Thank You … ❤️❤️❤️

Leave a Reply

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

We use cookies to ensure that we give you the best experience on our website. Privacy Policy