To-Do List Application Using PHP, MySQL and AJAX
To-Do lists are a great way to keep track of your daily tasks. In this tutorial, we will build our own to-do list using PHP, MySQL, and AJAX. This tutorial assumes that you have a basic understanding of HTML, PHP, MySQL, and jQuery. We will cover this tutorial in easy steps with a live demo of the To-Do List Application Using PHP & MySQL.
So let’s implement To-Do List Application Using PHP & MySQL. Look following folder and file structure:
- to-do-list-application-using-php-and-mysql
- assets
- css
- style.css
- js
- todo.js
- css
- templates
- header.php
- footer.php
- class
- DBConnection.php
- ToDoList.php
- index.php
- action.php
- assets
Step 1: Create MySQL Database Table
First, we will create database with the following table.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
CREATE TABLE `todo` ( `id` int(11) NOT NULL, `title` varchar(255) NOT NULL, `status` int(1) NOT NULL, `created_date` date NOT NULL DEFAULT current_timestamp() ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ALTER TABLE `todo` ADD PRIMARY KEY (`id`); ALTER TABLE `todo` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; COMMIT; |
Step 3: Database Connection class
Create a class file named
DBConnection.php
inside “class/” folder.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<?php /** * @package Database Config File * * @author WebHaunt Team * * @email info@webhaunt.com * */ class DbConnection { // Connect to an ODBC database using an alias private $_dbHostName = "localhost"; private $_dbName = "webhaunt_DB"; private $_dbUserName = "root"; private $_dbPassword = ""; private $_conn; // __construct public function __construct() { try { $this->_conn = new PDO("mysql:host=$this->_dbHostName;dbname=$this->_dbName", $this->_dbUserName, $this->_dbPassword, array(PDO::MYSQL_ATTR_FOUND_ROWS => true)); // set the PDO error mode to exception $this->_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { echo "Error connecting to MySQL server: " . $e->getMessage(); } } // return Connection public function returnConnection() { return $this->_conn; } } ?> |
Step 4: Create a class file named
ToDoList.php
inside “class/” folder.Manage CRUD Operations
- CREATE – INSERT record in database.
- READ – read records from database.
- UPDATE – Executes an UPDATE record in database
- DELETE – delete specified records from databse.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
<?php /** * @package Task class * * @author TechArise Team * * @email info@techarise.com * */ // include connection class include("DBConnection.php"); // ToDoList class ToDoList { protected $db; private $_todoID; private $_title; private $_description; private $_status; public function setToDoID($todoID) { $this->_todoID = $todoID; } public function setTitle($title) { $this->_title = $title; } public function setDescription($description) { $this->_description = $description; } public function setStatus($status) { $this->_status = $status; } // __construct public function __construct() { $this->db = new DBConnection(); $this->db = $this->db->returnConnection(); } // create ToDo List public function createToDo() { try { $sql = 'INSERT INTO todo (`title`, `status`) VALUES (:title, :status)'; $data = [ 'title' => $this->_title, 'status' => $this->_status, ]; $stmt = $this->db->prepare($sql); $stmt->execute($data); $lastID = $this->db->lastInsertId(); return $lastID; } catch (Exception $err) { die("Error description: " . $err); } } // update ToDo List public function updateToDo() { try { $sql = "UPDATE todo SET status=:status WHERE id=:todo_id"; $data = [ 'status' => $this->_status, 'todo_id' => $this->_todoID ]; $stmt = $this->db->prepare($sql); $stmt->execute($data); $status = $stmt->rowCount(); return $status; } catch (Exception $err) { die("Error description: " . $err); } } // getAll ToDo List public function getAllToDo() { try { $sql = "SELECT id, title, status FROM todo WHERE status != :status"; $stmt = $this->db->prepare($sql); $data = [ 'status' => $this->_status ]; $stmt->execute($data); $result = $stmt->fetchAll(\PDO::FETCH_ASSOC); return $result; } catch (Exception $err) { die("Error description: " . $err); } } // delete ToDo List public function deleteToDo() { try { $sql = "DELETE FROM todo WHERE id=:todo_id"; $stmt = $this->db->prepare($sql); $data = [ 'todo_id' => $this->_todoID ]; $stmt->execute($data); $status = $stmt->rowCount(); return $status; } catch (Exception $err) { die("Error description: " . $err); } } } ?> |
Step 5: Create action file named action.php
Manage request and return as JSON data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
<?php include_once 'class/ToDoList.php'; $todo = new ToDoList(); $_postData = $_POST; $json = array(); // create a new entry in the database if (!empty($_postData['action']) && $_postData['action'] == "create") { $todo->setTitle($_postData['title']); $todo->setStatus(0); $status = $todo->createToDo(); if (!empty($status)) { $json['msg'] = 'success'; $json['todo_id'] = $status; } else { $json['msg'] = 'failed'; $json['todo_id'] = ''; } header('Content-Type: application/json'); echo json_encode($json); } // update todo record in the database if (!empty($_postData['action']) && $_postData['action'] == "update") { $todo->setToDoID($_postData['todo_id']); $todo->setStatus($_postData['status']); $status = $todo->updateToDo(); if (!empty($status)) { $json['msg'] = 'success'; } else { $json['msg'] = 'failed'; } header('Content-Type: application/json'); echo json_encode($json); } // delete todo list from the database if (!empty($_postData['action']) && $_postData['action'] == "delete") { $todo->setToDoID($_postData['todo_id']); $status = $todo->deleteToDo(); if (!empty($status)) { $json['msg'] = 'success'; } else { $json['msg'] = 'failed'; } header('Content-Type: application/json'); echo json_encode($json); } ?> ?> |
Step 6: Create action file named index.php
We need to do is lay-out the structure for our main index page index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
<?php include_once 'class/ToDoList.php'; $todo = new ToDoList(); $todo->setStatus(2); $todoInfo = $todo->getAllToDo(); include('templates/header.php'); ?> <div class="content"> <div class="container"> <h2 class="mt-4 text-center">To-Do List Application Using PHP & MySQL</h2> <br> <div class="row"> <div class="col-lg-8 offset-2"> <div class="add-items d-flex"> <input type="text" class="form-control todo-list-input" placeholder="What do you need to do today?"> <button class="add btn btn-primary font-weight-bold todo-list-add-btn">Add</button> </div> <br> <div class="card"> <div class="card-header"> ToDo List </div> <div class="card-body"> <ul class="list-group list-group-flush todo-list"> <?php foreach ($todoInfo as $key => $element) { if (!empty($element['status']) && $element['status'] == 1) { $class = 'class="completed"'; $checked = 'checked="checked"'; } else { $class = ''; $checked = ''; } ?> <li class="list-group-item"> <input class="checkbox" type="checkbox" <?php print $checked; ?> data-utodoid="<?php print $element['id']; ?>"> <span><?php print $element['title'] ?></span> <i data-dtodoid="<?php print $element['id']; ?>" class="remove fa fa-times float-right"></i> </li> <?php } ?> </ul> </div> </div> </div> </div> </div> </div> <?php include('templates/footer.php'); ?> |
Create header.php and footer.php section of the webpage. The Bootstrap library is used to provide a better UI, so, include it in the header and footer section.
header.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content="WebHaunt"> <meta name="author" content="WebHaunt"> <title>To-Do List Application Using PHP & MySQL | WebHaunt</title> <link rel="icon" href="https://webhaunt.com/wp-content/uploads/2016/11/webhaunt-150x142.png" sizes="32x32" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.2/css/all.min.css" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/simple-line-icons/2.4.1/css/simple-line-icons.css" /> <link href="https://fonts.googleapis.com/css?family=Lato:300,400,700,300italic,400italic,700italic" rel="stylesheet" type="text/css"> <link href="assets/css/style.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-expand-lg navbar-dark static-top" style="background: linear-gradient(120deg, rgba(11,82,119,1) 0%, rgba(66,103,178,1) 100%);"> <div class="container"> <a class="navbar-brand font-weight-bold" href="https://webhaunt.com"> <h1>Web Haunt</h1> </a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarResponsive"> <ul class="navbar-nav ml-auto"> <li class="nav-item active"> <a class="nav-link" href="https://webhaunt.com">Home <span class="sr-only">(current)</span> </a> </li> <li class="nav-item"> <a class="nav-link" href="https://webhaunt.com/php-script-free-demo">Live Demos</a> </li> </ul> </div> </div> </nav> |
footer.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<footer id="colophon" class="site-footer" role="contentinfo"> <div class="site-info"> <div class="site-info-inside"> <div class="container"> <div class="row"> <div class="col"> <div class="credits-wrapper"> <div class="credits credits-blog">Copyright © 2016 - 2023 <a href="https://webhaunt.com" title="webhaunt.com">WEBHAUNT.COM</a> All rights reserved.</div> </div><!-- .credits --> </div><!-- .col --> </div><!-- .row --> </div><!-- .container --> </div><!-- .site-info-inside --> </div><!-- .site-info --> </footer> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script> <script src="assets/js/todo.js"></script> </body> </html> |