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.
π‘ Explore More PHP Learning Tools & Resources
π
PHP Practice Quiz
Test your PHP skills with real coding questions and scoring.
π
PHP Interview Questions
Prepare for interviews with common PHP questions and answers.
π
Educational AI Tutor
Ask PHP questions and get instant AI-powered explanations.
π§
Question Generator
Auto-generate PHP interview questions for quick practice.