User login and registration with php & mysql (+source code)
I am here with another php tutorial that is user login and registration with php & mysql.
Live Demo :
Go To Live DemoLocal setup of user login and registration with php
Go to your localhost directory like htdocs or www. Then open your command terminal and run the following command
git clone https://github.com/SATPAL-BHARDWAJ/user-auth-php.git
It will clone the user-auth-php project to your local server.
Now, you need to change a few things, open your code editor and add this project there. Open the file config/include.php and replace the BASE_PATH constant value with your project directory.
For example, my project is in the following directory
htdocs/projects/user-auth-php
So,
define('BASE_PATH', '/projects/user-auth-php');
Save it. And now open your web browser and type following url
localhost/path-to/user-auth-php
Replace “path-to” with your actual directory, if you have any otherwise if you clone this project to the root like htdocs or www directly then use only “/user-auth-php”.
Now, go to config/conn.php and replace the following dbname, username and password as per your local server credentials.
private $server = "mysql:host=localhost;dbname=userAuth"; private $username = "root"; private $password = "";
Let’s go through the code one by one.
Create the user table for login and registration process
Create the database with the name userAuth or anything that you want. Then execute the below SQL query to create the user table.
CREATE TABLE `users` ( `id` bigint(20) NOT NULL, `firstname` varchar(191) NOT NULL, `lastname` varchar(191) DEFAULT NULL, `password` varchar(191) NOT NULL, `email` varchar(191) NOT NULL, `created_at` timestamp NOT NULL DEFAULT current_timestamp(), `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Alter this table and add the primary key with auto increment value.
ALTER TABLE `users` ADD PRIMARY KEY (`id`); ALTER TABLE `users` MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT;
Our column Id is auto increment so we don’t need to pass anything as id for new registered users. Next, we have updated_at and created_at both timestamps are current_timestamp so, again we don’t need to pass these too.
We will use firstname, lastname, email and password to register new users. That’s it.
PHP Login and registration pages
Here I have used php functions to manage the form validations and php session related things. I have already written an article about php form validation, you can check that.
We are also using a routing system which is simply an array of routes and we are getting the actual file path from that array.
Like when a user calls the https://example.com/login, we are actually getting the auth.php file as a view. So, we have set up the htaccess file to redirect all http calls to the index.php where we are using the routes array to get the actual file path. This is how our php routing system works.
The auth.php file given below and it is used for both login and registration.
<?php if (isset($_SESSION['user'])) { redirect('\\'); } ?> <div class="auth-box-container"> <div class="formBox <?php echo hasErrorBag() ? 'level-reg' : 'level-login' ?>"> <div class="box boxShaddow"></div> <div class="box loginBox"> <h2>LOGIN</h2> <form class="form" method='POST' action='<?php url('/app/login'); ?>'> <div class="f_row"> <label>Username</label> <input type="email" name="email" class="input-field" required> <u></u> </div> <div class="f_row last"> <label>Password</label> <input type="password" name="password" class="input-field" required> <u></u> </div> <button type="button" class="btn"><span>GO</span><u></u> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 415.582 415.582" xml:space="preserve"> <path d="M411.47,96.426l-46.319-46.32c-5.482-5.482-14.371-5.482-19.853,0L152.348,243.058l-82.066-82.064 c-5.48-5.482-14.37-5.482-19.851,0l-46.319,46.32c-5.482,5.481-5.482,14.37,0,19.852l138.311,138.31 c2.741,2.742,6.334,4.112,9.926,4.112c3.593,0,7.186-1.37,9.926-4.112L411.47,116.277c2.633-2.632,4.111-6.203,4.111-9.925 C415.582,102.628,414.103,99.059,411.47,96.426z" /> </svg> </button> <div class="f_link"> <a href="" class="resetTag">Forgot your password?</a> </div> </form> </div> <div class="box forgetbox"> <a href="#" class="back icon-back"> <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 199.404 199.404" style="enable-background:new 0 0 199.404 199.404;" xml:space="preserve"> <polygon points="199.404,81.529 74.742,81.529 127.987,28.285 99.701,0 0,99.702 99.701,199.404 127.987,171.119 74.742,117.876 199.404,117.876 " /> </svg> </a> <h2>Reset Password</h2> <form class="form"> <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, </p> <div class="f_row last"> <label>Email Id</label> <input type="text" class="input-field" required> <u></u> </div> <button class="btn"><span>Reset</span><u></u> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 415.582 415.582" xml:space="preserve"> <path d="M411.47,96.426l-46.319-46.32c-5.482-5.482-14.371-5.482-19.853,0L152.348,243.058l-82.066-82.064 c-5.48-5.482-14.37-5.482-19.851,0l-46.319,46.32c-5.482,5.481-5.482,14.37,0,19.852l138.311,138.31 c2.741,2.742,6.334,4.112,9.926,4.112c3.593,0,7.186-1.37,9.926-4.112L411.47,116.277c2.633-2.632,4.111-6.203,4.111-9.925 C415.582,102.628,414.103,99.059,411.47,96.426z" /> </svg> </button> </form> </div> <div class="box registerBox"> <span class="reg_bg"></span> <h2>Register</h2> <form class="form" method='POST' action='<?php url('/app/signup'); ?>'> <div class="d-flex"> <div class="f_row"> <label>First Name</label> <input type="text" name="firstname" class="input-field"> <u></u> <?php showFormError('firstname') ?> </div> <div class="f_row"> <label>Last Name</label> <input type="text" name="lastname" class="input-field"> <u></u> <?php showFormError('lastname'); ?> </div> </div> <div class="f_row"> <label>Email</label> <input type="email" name="email" class="input-field"> <u></u> <?php showFormError('email'); ?> </div> <div class="f_row"> <label>Password</label> <input type="password" name="password" class="input-field"> <u></u> <?php showFormError('password'); ?> </div> <div class="f_row last"> <label>Repeat Password</label> <input type="password" name="repassword" class="input-field"> <u></u> <?php showFormError('repassword'); ?> </div> <button type="submit" class="btn-large">NEXT</button> </form> </div> <a href="#" class="regTag icon-add" title="Create new account"> <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 357 357" style="enable-background:new 0 0 357 357;" xml:space="preserve"> <path d="M357,204H204v153h-51V204H0v-51h153V0h51v153h153V204z" /> </svg> </a> </div> </div>
How does login work?
We have loginController.php to handle login related processes. We are also updating the last login here. All errors managed by session helper function.
<?php if(isset($_POST['email'])){ $conn = $pdo->open(); $email = $_POST['email']; $password = $_POST['password']; if ( '' === trim($email) || '' === trim($password) ) { session('error', 'Credentials missing!'); redirect('\login'); } try{ $stmt = $conn->prepare("SELECT *, COUNT(*) AS numrows FROM users WHERE email = :email"); $stmt->execute(['email'=>$email]); $row = $stmt->fetch(); if($row['numrows'] > 0){ if(password_verify($password, $row['password'])){ session('user', $row['id']); $now = date('Y-m-d H:i:s'); $stmt = $conn->prepare("UPDATE users SET updated_at=:updated_at WHERE id=:id"); $stmt->execute(['updated_at' => $now, 'id' => $row['id']]); redirect('\\'); } else{ session('error', 'Incorrect Password'); } } else{ session('error', 'Email not found'); } } catch(PDOException $e){ echo "There is some problem in connection: " . $e->getMessage(); } } else{ session('error', 'Input login credentails first'); } $pdo->close(); redirect('\login');
How does logout work?
Logout means simply destroy the user sessions and then redirect the user to the login page.
<?php session_start(); session_destroy(); redirect('\login'); ?>
How does register work?
Registering a user has some validation rules and we have used again helper functions to manage form validations and showing the errors on the form. We have used hashed password for better security.
<?php if(isset($_POST['email'])){ signup_validation(); $firstname = $_POST['firstname']; $lastname = $_POST['lastname']; $email = $_POST['email']; $password = $_POST['password']; $repassword = $_POST['repassword']; if($password != $repassword){ setErrorsBag('repassword', 'Passwords did not match'); redirect('\signup'); } else{ $conn = $pdo->open(); $stmt = $conn->prepare("SELECT COUNT(*) AS numrows FROM users WHERE email=:email"); $stmt->execute(['email'=>$email]); $row = $stmt->fetch(); if($row['numrows'] > 0){ session('error', 'Email already taken'); redirect('\signup'); } else{ $password = password_hash($password, PASSWORD_DEFAULT); try{ $stmt = $conn->prepare("INSERT INTO users (email, password, firstname, lastname) VALUES (:email, :password, :firstname, :lastname)"); $stmt->execute(['email'=>$email, 'password'=>$password, 'firstname'=>$firstname, 'lastname'=>$lastname]); $userid = $conn->lastInsertId(); session('user', $userid); redirect('\\'); } catch(PDOException $e){ session('error', $e->getMessage()); redirect('\signup'); } $pdo->close(); } } } else{ session('error', 'Fill up signup form first'); redirect('\signup'); } function signup_validation() { resetErrorBag(); $inputs = [ 'firstname', 'lastname', 'email', 'password', 'repassword', ]; $messages = [ 'firstname' => 'First name is required', 'lastname' => 'Last name is required', 'email' => 'Email is required', 'password' => 'Password is required', 'repassword' => 'Confirm password is required', ]; foreach($_POST as $input => $value) { if ( in_array($input, $inputs) && !$value ) { setErrorsBag($input, $messages[$input]); } } if ( hasErrorBag() ) { redirect('\signup'); } }
Create the dashboard page for logged-in users
Dashboard page simply redirect the user back to login if user is not logged in yet. If user is already logged in it will show some information about the user as you can see in the output image below.
<?php if ( !isset($_SESSION['user']) ) { redirect('\login'); } ?> <div class="container my-5 d-flex justify-content-center"> <div class="card" style="width: 25rem;"> <img src="<?php echo url('/resources/assets/images/user-satisfaction.png') ?>" class="card-img-top" alt="..."> <div class="card-body"> <h5 class="card-title text-capitalize"><?php echo $user['firstname'].' '.$user['lastname']; ?></h5> <p class="card-text">You are successfuly loggedIn!</p> </div> <ul class="list-group list-group-flush"> <li class="list-group-item"><?php echo $user['email']; ?></li> <li class="list-group-item">Registered at : <?php echo $user['created_at']; ?></li> <li class="list-group-item">Last login at : <?php echo $user['updated_at']; ?></li> </ul> <div class="card-body"> <a href="<?php url('\logout'); ?>" class="card-link">Logout</a> </div> </div> </div>
Hope you find this article useful.