This tutorial is going to be an exciting and thrilling one as we are going to create a simple ToDo App in PHP with authentication with an actual database. We are also going to use bootstrap for the front end and jquery in some parts as well. Also, we are going to implement the feature of login and signup for the users. We are going to use MySQL database for database and PHP for the backend. Also, we will, later on, add the feature to add, view, and delete to-do items.
Note: The to-do for all the users will be private to them only.
We will also learn to use md5 hashing for the passwords to make our web app more secure.
Output for ToDo App in PHP:
Before we start building ToDo App in PHP, let’s first have a look at what we are actually going to develop.
Video output:
Image output:
Download the full project resources:
Requirements
- Xampp
- Text editor (Vs code, Sublime text, Atom)
- Browser (Chrome, Firefox, Edge, Opera)
- Basic knowledge of HTML, CSS, PHP, MySQL, and jquery
Features
- Login
- Signup
- Add todo
- View todo
- Delete todo
- Logout
Note: The to-do for all the users will be private to them only.
Project setup
Xampp setup
Note if you don’t have xampp installed, follow this link to install xampp. Before jumping right into code make sure that you have Xampp installed and these 2 important processes running Apache and MySQL.
Project folder structure
Coding ToDo App in PHP with authentication
We will do all the code in the c/Xampp/htdocs folder. We will create a new folder with the name todoPhp and open it in the text editor. So first we will draw the simple form for the login and signup and pass the parameters to a function that will later process with PHP.
index.php
The code for the form will be something like this and it will be in the index.php file
<!-- Login Form --> <div class="container"> <div class="row"> <div class="col-md-6 offset-md-3 formcontainer"> <h1 class="d-flex justify-content-center mt-5">LOGIN FORM</h1> <form method="post" action="assets/backend/auth.php" class="border rounded p-4 border-primary login-form"> <div class="mb-3"> <label for="login_email" class="form-label">Email address</label> <input type="email" class="form-control" id="login_email" name="login_email" required> </div> <div class="mb-3"> <label for="login_password" class="form-label">Password</label> <input type="password" class="form-control" id="login_password" name="login_password" required> </div> <button type="submit" name="login-btn" id="login-btn" class="btn btn-primary">Login</button> </form> <div class="d-flex justify-content-end"> <a href="">Forget Password</a> </div> <div class="d-flex justify-content-center"> Don't have an account ?? <a href="register.php"> Sign Up</a> </div> </div> </div> </div> <!-- ./Login Form --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
register.php
Also, we will now create the registered user page and the code for the form will be something like this and it will be in the register.php file.
<div class="container"> <div class="row"> <div class="col-md-6 offset-md-3 formcontainer "> <h1 class="d-flex justify-content-center mt-5">SIGNUP FORM</h1> <form method="post" action="assets/backend/auth.php" class="border rounded p-4 border-primary login-form"> <div class="mb-3"> <label for="username" class="form-label">Username</label> <input type="text" class="form-control" id="username" name="username" placeholder="Enter name" required> </div> <div class="mb-3"> <label for="email" class="form-label">Email address</label> <input type="email" class="form-control" id="email" name="email" placeholder="Enter email" required> </div> <div class="mb-3"> <label for="password" class="form-label">Password</label> <input type="password" class="form-control" id="password" name="password" placeholder="Enter password" required> </div> <div class="mb-3"> <label for="c_password" class="form-label">Confirm Password</label> <input type="text" class="form-control" id="c_password" name="c_password" placeholder="Confirm Password" required> </div> <button type="submit" id="signup-btn" name="signup-btn" class="btn btn-primary d-flex justify-content-center">Sign Up</button> </form> <div class="d-flex justify-content-center"> Already have an account ?? <a href="index.php"> Login</a> </div> </div> </div> </div> <!-- ./Signup Form --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
Database for project
Before we go into more detail, we will first create the database and the table for the users and the to-do items.
To create the required tables for ToDo App in PHP, we will add a new database by the name todophp in the PHPMyAdmin, and then we will import the SQL file that is given in the resources.
So, first, we will create the database and the table for the users and the to-do items.
Steps to create new database and tables:
1. First, visit http://localhost/phpmyadmin/ in your browser.
2. Click on the new icon on the left.
3. After that, fill in the text box with todophp and hit create button.
4. After that go to the import button and select the file and click the import button on the bottom.
If successful you will see a screen something like this
todophp.sql
This is the file to import.
-- phpMyAdmin SQL Dump -- version 5.2.0 -- https://www.phpmyadmin.net/ -- -- Host: 127.0.0.1 -- Generation Time: Dec 04, 2022 at 12:57 PM -- Server version: 10.4.27-MariaDB -- PHP Version: 7.4.33 SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; START TRANSACTION; SET time_zone = "+00:00"; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8mb4 */; -- -- Database: `todophp` -- -- -------------------------------------------------------- -- -- Table structure for table `todolist` -- CREATE TABLE `todolist` ( `id` int(11) NOT NULL, `user_id` int(11) NOT NULL, `tasks` varchar(255) NOT NULL, `created_at` timestamp NOT NULL DEFAULT current_timestamp(), `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -- -------------------------------------------------------- -- -- Table structure for table `users` -- CREATE TABLE `users` ( `id` int(11) NOT NULL, `username` varchar(255) NOT NULL, `email` varchar(255) NOT NULL, `password` varchar(255) NOT NULL, `status` int(11) NOT NULL DEFAULT 1, `created_at` timestamp NOT NULL DEFAULT current_timestamp(), `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -- -- Indexes for dumped tables -- -- -- Indexes for table `todolist` -- ALTER TABLE `todolist` ADD PRIMARY KEY (`id`), ADD KEY `user_id` (`user_id`); -- -- Indexes for table `users` -- ALTER TABLE `users` ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `email` (`email`); -- -- AUTO_INCREMENT for dumped tables -- -- -- AUTO_INCREMENT for table `todolist` -- ALTER TABLE `todolist` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=14; -- -- AUTO_INCREMENT for table `users` -- ALTER TABLE `users` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7; -- -- Constraints for dumped tables -- -- -- Constraints for table `todolist` -- ALTER TABLE `todolist` ADD CONSTRAINT `todolist_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`); COMMIT; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
After we have run the queries the tables for users and todos will be created.
db_connection.php
In the assets/backend folder, we will create a db_connection.php file to connect to our database of ToDo App in PHP.
<?php // database Connection $hostname = "localhost"; $username = "root"; $password = ""; $db = "todophp"; $conn = new mysqli($hostname,$username,$password,$db); if($conn->connect_error){ die("connection error".$conn->connect_error); } session_start(); error_reporting('1'); ?> <!--Now in the assets/backend folder--> <!--We will define the logic for login and register in our auth.php file--> <?php include 'db_connection.php'; // ========== LOGIN USERS ========== $login_email = $_POST['login_email']; $login_password = md5($_POST['login_password']); if(isset($_POST['login-btn'])){ if(filter_var($login_email, FILTER_VALIDATE_EMAIL)){ $select = "SELECT * FROM `users` WHERE email = '$login_email'"; $query = mysqli_query($conn, $select); $row = mysqli_fetch_assoc($query); if($row){ if($row['password'] == $login_password){ $_SESSION['username'] = $row['username']; $_SESSION['user_id'] = $row['id']; $_SESSION['email'] = $row['email']; $_SESSION['status'] = $row['status']; $_SESSION['logged_in'] = true; header("location:http://localhost/todoPhp/home.php?username=$row[username]"); }else{ echo "<script>alert('Wrong Password...try again!!'); window.location='../../index.php';</script>"; } }else{ echo "<script>alert('User does not exist...try again!!'); window.location='../../index.php';</script>"; } }else{ echo "<script>alert('Invalid email...Enter a valid email!!'); window.location='../../index.php';</script>"; } } // ========== SIGNUP USERS ========== $username = $_POST['username']; $email = $_POST['email']; $password = $_POST['password']; $c_password = $_POST['c_password']; if(isset($_POST['signup-btn'])){ if(filter_var($email, FILTER_VALIDATE_EMAIL)){ if($password == $c_password){ $select = "SELECT * FROM `users` WHERE email = '$email'"; $query = mysqli_query($conn, $select); $row = mysqli_fetch_assoc($query); if(!$row){ $insert = "INSERT INTO `users`(`username`, `email`, `password`, `created_at`, `updated_at`) VALUES ('$username','$email',md5($password),CURRENT_TIMESTAMP,CURRENT_TIMESTAMP)"; $query = mysqli_query($conn,$insert); if($query){ echo "<script>alert('Your account has been created successfully!!'); window.location='../../index.php';</script>"; }else{ echo "<script>alert('Something went wrong...try again!!'); window.location='../../register.php';</script>"; } }else{ echo "<script>alert('User already exists...try again!!'); window.location='../../register.php';</script>"; } }else{ echo "<script>alert('Password and Confirm Password does not match...try again!!'); window.location='../../register.php';</script>"; } }else{ echo "<script>alert('Invalid email...Enter a valid email!!'); window.location='../../register.php';</script>"; } } ?>
Hashing the password
Here, instead of storing the normal password, we store the md5 hashed password in the database so that the password is not stored in plain text in the database.
We do that by this function in PHP
$hashedPassword = md5($password);
Also during login, we check the md5 hashed password with the md5 hashed password in the database, thus ensuring that the passwords are not compromised.
To add the logout functionality we add this line in the logout.php file which is in assets/backend/logout.php.
<?php session_start(); session_destroy(); header("location:http://localhost/todoPhp/index.php?msg=logout"); ?>
To add all the UI for the todo’s we do add these lines in our home.php file.
<?php include 'assets/backend/db_connection.php'; if($_SESSION['logged_in'] == true){ include 'assets/backend/todo.php'; ?> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Todo App</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous"> <link rel="stylesheet" href="assets/css/style.css"> </head> <body> <!-- Navbar --> <nav class="navbar bg-light"> <div class="container"> <span class="navbar-brand mb-0 h1"><?php echo $_SESSION['username'];?></span> <div class="d-flex justify-content-end logout-btn"><a href="assets/backend/logout.php">Logout</a></div> </div> </nav> <!-- ./Navbar --> <!-- Todo section --> <div class="container"> <div class="row"> <div class="col-md-6 offset-md-3"> <!-- add todo --> <div id="add-btn" class=" d-flex justify-content-center mt-5"> <span class="btn btn-primary"><i class="fa-solid fa-plus"></i> Add Todo</span> </div> <div id="add-todo-form" class="mt-5"> <form action="assets/backend/todo.php" method="post" > <div class="input-group mb-3"> <input type="text" class="form-control" id="add-todo" name="add-todo" placeholder="Enter your todo here" > <button class="btn btn-primary" name="add-todo-btn" id="add-todo-btn" type="submit">Add</button> </div> </form> </div> <!-- ./add todo --> <!-- todo table --> <table class="table border rounded mt-5" > <thead> <tr> <th scope="col">#</th> <th class="text-center" scope="col">Tasks</th> <th class="text-center" scope="col"> Actions </th> </tr> </thead> <tbody> <?php $sno = 1; while($row = mysqli_fetch_assoc($s_query)){?> <tr> <th scope="row" ><?php echo $sno++;?></th> <td class="text-center"> <div class="task-list"> <?php echo $row['tasks'];?> </div> </td> <td class="text-center"> <form action="assets/backend/todo.php?id=<?php echo $row['id'];?>" method="post"> <button class="btn btn-danger" name="dlt-todo-btn" id="dlt-todo-btn" type="submit">Delete</button> </form> </td> </tr> <?php }?> </tbody> </table> <!-- ./todo table --> </div> </div> </div> <!-- ./Todo section --> <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/js/all.min.js" integrity="sha512-rpLlll167T5LJHwp0waJCh3ZRf7pO6IT1+LZOhAyP6phAirwchClbTZV3iqL3BMrVxIYRbzGTpli4rfxsCK6Vw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script> <script> $(document).ready(function(){ $( "#add-btn" ).click(function() { $("#add-todo-form").toggle(); }); }); </script> </body> </html> // To take care of if the user tries to access the home.php page without logging in we add this line in the home.php file // to redirect the user to the login page <?php }else{ header("location:http://localhost/todoPhp/index.php?msg=login_first"); } ?>
todo.php
To add the functionality for adding and deleting the todo’s we define all the backend logic in assets/backend/tood.php.
<?php include 'db_connection.php'; $user_id = $_SESSION['user_id']; // =========== Fetch tasks list ========== $select = "SELECT * FROM `todolist` WHERE user_id = '$user_id'"; $s_query = mysqli_query($conn,$select); // $row = mysqli_fetch_assoc($query); // =========== ADD TASKS ========= $tasks = $_POST['add-todo']; if(isset($_POST['add-todo-btn'])){ $insert = "INSERT INTO `todolist`(`user_id`, `tasks`, `created_at`, `updated_at`) VALUES ('$user_id','$tasks', CURRENT_TIMESTAMP,CURRENT_TIMESTAMP)"; $query = mysqli_query($conn,$insert); if($query){ echo "<script> window.location='../../home.php';</script>"; }else{ // echo $user_id; echo "<script>alert('Something Went wrong...try again!!'); window.location='../../home.php';</script>"; } } // ============== Delete Task =========== if(isset($_POST['dlt-todo-btn'])){ $row_id = $_GET['id']; $delete = "DELETE FROM `todolist` WHERE id = $row_id"; $d_query = mysqli_query($conn,$delete); if($d_query){ echo "<script> window.location='../../home.php';</script>"; }else{ // echo $row['id']; echo "<script>alert('Something Went wrong...try again!!'); window.location='../../home.php';</script>"; } } ?>
style.css
On top of the usual to make the project more pleasing we add the styles.css file in our assets/css folder.
.login-form{ margin : 5% auto; } .logout-btn a{ text-decoration : none; color : #000000; } #add-todo-form{ display : none; } .hidden{ display : none; }
To bundle up the whole project of the ToDo App in PHP, this is the zip file for it, after downloading the zip file extract it and place it in the htdocs folder of your c/xampp folder. After this create a new table by visiting the localhost/PHPMyAdmin and import the SQL file from the zip file. After this, you can run the project by visiting localhost/todoPhp/index.php.
Thank you for visiting our website.
Also Read:
- Imagination to Reality, Unlocking the Future: Genesis Physics Engine for 4D Simulation
- Simple Code to compare Speed of Python, Java, and C++?
- Falling Stars Animation on Python.Hub October 2024
- Most Underrated Database Trick | Life-Saving SQL Command
- Python List Methods
- Top 5 Free HTML Resume Templates in 2024 | With Source Code
- How to See Connected Wi-Fi Passwords in Windows?
- 2023 Merry Christmas using Python Turtle
- 23 AI Tools You Won’t Believe are Free
- Python 3.12.1 is Now Available
- Best Deepfake Apps and Websites You Can Try for Fun
- Amazon launched free Prompt Engineering course: Enroll Now
- 10 GitHub Repositories to Master Machine Learning
- Hello World in 35 Programming Languages
- How to Scrape Data From Any Website with Python?
- Become Job Ready With Free Harvard Computer Science course: Enroll Now
- Free Python Certification course from Alison: Good for Resume
- Download 1000+ Projects, All B.Tech & Programming Notes, Job, Resume & Interview Guide, and More – Get Your Ultimate Programming Bundle!
- Udacity Giving Free Python Course: Here is how to Enroll
- Love Babbar’s Income Revealed
- Top 5 Websites to Learn Programming in 2024
- Python Internship for college students and freshers: Apply Here
- Microsoft Giving Free Python Course in 2023: Enroll Now
- Top 5 Free Python Courses on YouTube in 2024
- Complete Python Roadmap for Beginners in 2024
- New secrets to Earn money with Python in 2024
- Connect with HR Directly – Job Hack
- Google offering free Python course: Enroll Today
- What is an AI Tool?
- Google Internship 2024