πŸ’‘ Ask Tutor

Build a Simple To-Do App with PHP + MySQL

Why Build a To-Do App?

A To-Do List application is a perfect beginner project because it covers:

  • Working with forms
  • Managing database operations (CRUD)
  • Dynamic content rendering with PHP
  • A real-world use case with practical functionality

Folder Structure πŸ“

Plaintext
todo-app/
β”œβ”€β”€ index.php
β”œβ”€β”€ add.php
β”œβ”€β”€ update.php
β”œβ”€β”€ delete.php
└── db.php

Step 1: Create the Database and Table

Use phpMyAdmin or CLI to create your database:

SQL
CREATE DATABASE tododb;

USE tododb;

CREATE TABLE todos (
  id INT AUTO_INCREMENT PRIMARY KEY,
  task TEXT NOT NULL,
  status TINYINT DEFAULT 0, -- 0 = pending, 1 = done
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Step 2: Database Connection – db.php

PHP
<?php
try {
  $pdo = new PDO("mysql:host=localhost;dbname=tododb", "root", "");
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
  die("Database connection failed: " . $e->getMessage());
}
?>

Step 3: Add New Task – add.php

<?php
require 'db.php';

if ($_SERVER["REQUEST_METHOD"] === "POST") {
  $task = trim($_POST['task']);

  if (!empty($task)) {
    $stmt = $pdo->prepare("INSERT INTO todos (task) VALUES (:task)");
    $stmt->execute(['task' => $task]);
  }

  header("Location: index.php");
  exit;
}
?>

Step 4: Delete Task – delete.php

PHP
<?php
require 'db.php';

if (isset($_GET['id'])) {
  $id = $_GET['id'];
  $stmt = $pdo->prepare("DELETE FROM todos WHERE id = :id");
  $stmt->execute(['id' => $id]);
}

header("Location: index.php");
exit;
?>

Step 5: Update Task Status – update.php

<?php
require 'db.php';

if (isset($_GET['id']) && isset($_GET['status'])) {
  $id = $_GET['id'];
  $status = $_GET['status'];
  $stmt = $pdo->prepare("UPDATE todos SET status = :status WHERE id = :id");
  $stmt->execute(['status' => $status, 'id' => $id]);
}

header("Location: index.php");
exit;
?>

Step 6: Main Interface – index.php

<?php
require 'db.php';
$stmt = $pdo->query("SELECT * FROM todos ORDER BY created_at DESC");
$todos = $stmt->fetchAll();
?>

<!DOCTYPE html>
<html>
<head>
  <title>PHP To-Do List</title>
  <style>
    body { font-family: Arial; max-width: 600px; margin: auto; padding: 30px; }
    form input[type="text"] { width: 80%; padding: 10px; }
    form input[type="submit"] { padding: 10px; }
    ul { list-style: none; padding: 0; }
    li { margin: 10px 0; padding: 10px; border-bottom: 1px solid #ddd; }
    .done { text-decoration: line-through; color: gray; }
    a { text-decoration: none; color: red; margin-left: 10px; }
  </style>
</head>
<body>

<h2>πŸ“ PHP To-Do List</h2>

<form action="add.php" method="post">
  <input type="text" name="task" placeholder="Enter your task..." required>
  <input type="submit" value="Add Task">
</form>

<ul>
<?php foreach ($todos as $todo): ?>
  <li>
    <span class="<?= $todo['status'] ? 'done' : '' ?>">
      <?= htmlspecialchars($todo['task']) ?>
    </span>

    <?php if (!$todo['status']): ?>
      <a href="update.php?id=<?= $todo['id'] ?>&status=1">Mark as Done</a>
    <?php else: ?>
      <a href="update.php?id=<?= $todo['id'] ?>&status=0">Undo</a>
    <?php endif; ?>

    <a href="delete.php?id=<?= $todo['id'] ?>">Delete</a>
  </li>
<?php endforeach; ?>
</ul>

</body>
</html>

Features Covered

  • Add, read, update, and delete tasks from a database
  • Mark tasks as “done” and “undo” them
  • Store tasks with timestamps
  • Automatically update UI with dynamic list from the database

Common Mistakes to Avoid

  • Not escaping user input (use htmlspecialchars() on display)
  • Using raw SQL (always use prepared statements)
  • Forgetting to redirect after actions (avoid resubmissions)
  • Not checking if task is empty before inserting

Best Practices

  • Keep your code modular by separating DB logic (db.php)
  • Always sanitize and escape user input
  • Use prepared statements to avoid SQL injection
  • Redirect users after actions to prevent resubmissions
  • Style your list for readability and UX

Notes:

  • You’ve now built a fully working to-do app with PHP and MySQL
  • It demonstrates real-world usage of forms, database queries, and CRUD logic
  • The same concepts power CMS systems, admin panels, and web apps

Practice Tasks

Task 1: Add Due Date
Enhance the table to include a due_date field and display it below the task.

Task 2: Add Edit Option
Let users click “Edit”, load the task into a form, update the text, and submit changes.

Task 3: Filter Tasks
Add buttons or a dropdown to filter between: All, Completed, and Pending tasks.