Project Overview
A To-Do List Application allows users to add, view, edit, and delete tasks. This project helps in understanding CRUD (Create, Read, Update, Delete) operations, form handling, and database interactions using PHP and MySQL.
Prerequisites
Before starting, ensure you have the following:
- Web Server: Apache (using XAMPP, WAMP, or MAMP)
- PHP: Version 7.4 or higher
- MySQL: For database management
- Code Editor: VS Code, Sublime Text, PHPStorm, etc.
- Composer: For dependency management (optional)
Step-by-Step Procedure
1. Setting Up the Development Environment
- Install XAMPP:
- Download from XAMPP Official Website.
- Follow the installation wizard and install it in the default directory.
- Start Apache and MySQL:
- Open the XAMPP Control Panel.
- Start the Apache and MySQL modules.
2. Creating the Database
- Access phpMyAdmin:
- Navigate to
http://localhost/phpmyadmin/
in your browser.
- Navigate to
- Create a New Database:
- Click on “New” in the left sidebar.
- Name the database
todo_app
. - Choose “utf8mb4_unicode_ci” as the collation.
- Click “Create”.
- Create a
tasks
Table:- Select the
todo_app
database. - Click on “New” to create a table.
- Define the table with the following fields:
- Click “Save”.
- Select the
3. Project Structure
Organize your project files as follows:
todo-app/
├── assets/
│ ├── css/
│ │ └── styles.css
│ └── js/
│ └── scripts.js
├── config/
│ └── db.php
├── templates/
│ ├── header.php
│ └── footer.php
├── add_task.php
├── edit_task.php
├── delete_task.php
├── index.php
└── README.md
4. Configuration
a. Database Connection (config/db.php
)
Create a file named db.php
inside the config
directory to handle database connections.
<?php
// config/db.php
$host = 'localhost';
$db = 'todo_app';
$user = 'root'; // Default XAMPP MySQL user
$pass = ''; // Default XAMPP MySQL password is empty
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // Enable exceptions
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // Fetch associative arrays
PDO::ATTR_EMULATE_PREPARES => false, // Disable emulation
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
// Handle connection errors
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
?>
5. Creating Reusable Templates
a. Header (templates/header.php
)
<?php
// templates/header.php
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>To-Do List Application</title>
<link rel="stylesheet" href="/todo-app/assets/css/styles.css">
</head>
<body>
<header>
<h1>To-Do List Application</h1>
<nav>
<a href="/todo-app/index.php">Home</a>
<a href="/todo-app/add_task.php">Add Task</a>
</nav>
</header>
<main>
b. Footer (templates/footer.php
)
<?php
// templates/footer.php
?>
</main>
<footer>
<p>© <?php echo date("Y"); ?> Your Company Name</p>
</footer>
<script src="/todo-app/assets/js/scripts.js"></script>
</body>
</html>
6. Styling the Application (assets/css/styles.css
)
Add basic styles to enhance the appearance.
/* assets/css/styles.css */
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
header, footer {
background-color: #333;
color: #fff;
padding: 10px 20px;
}
header h1, footer p {
margin: 0;
}
nav a {
color: #fff;
margin-right: 15px;
text-decoration: none;
}
main {
padding: 20px;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
table, th, td {
border: 1px solid #ddd;
}
th, td {
padding: 12px;
text-align: left;
}
th {
background-color: #f4f4f4;
}
a {
color: #007BFF;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
button {
padding: 8px 12px;
background-color: #28a745;
color: #fff;
border: none;
cursor: pointer;
}
button:hover {
background-color: #218838;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="text"] {
width: 100%;
padding: 8px;
box-sizing: border-box;
}
select {
width: 100%;
padding: 8px;
box-sizing: border-box;
}
7. Building the Home Page (index.php
)
This page displays all tasks with options to edit or delete them.
<?php
// index.php
require 'config/db.php';
require 'templates/header.php';
// Fetch all tasks
$stmt = $pdo->query('SELECT * FROM tasks ORDER BY created_at DESC');
$tasks = $stmt->fetchAll();
?>
<h2>My To-Do List</h2>
<?php if ($tasks): ?>
<table>
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Status</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($tasks as $task): ?>
<tr>
<td><?php echo htmlspecialchars($task['id']); ?></td>
<td><?php echo htmlspecialchars($task['title']); ?></td>
<td><?php echo htmlspecialchars($task['status']); ?></td>
<td><?php echo htmlspecialchars($task['created_at']); ?></td>
<td>
<a href="edit_task.php?id=<?php echo $task['id']; ?>">Edit</a> |
<a href="delete_task.php?id=<?php echo $task['id']; ?>" onclick="return confirm('Are you sure you want to delete this task?');">Delete</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else: ?>
<p>No tasks found. <a href="add_task.php">Add a new task</a>.</p>
<?php endif; ?>
<?php
require 'templates/footer.php';
?>
8. Adding New Tasks (add_task.php
)
This page allows users to add new tasks to the list.
<?php
// add_task.php
require 'config/db.php';
require 'templates/header.php';
$errors = [];
$success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Sanitize and validate input
$title = trim($_POST['title']);
$status = trim($_POST['status']);
if (empty($title)) {
$errors[] = 'Task title is required.';
}
if (empty($status)) {
$errors[] = 'Task status is required.';
} elseif (!in_array($status, ['pending', 'completed'])) {
$errors[] = 'Invalid task status.';
}
if (empty($errors)) {
// Insert into database
$stmt = $pdo->prepare('INSERT INTO tasks (title, status) VALUES (?, ?)');
if ($stmt->execute([$title, $status])) {
$success = 'Task added successfully.';
// Clear form fields
$title = $status = '';
} else {
$errors[] = 'There was an error adding the task. Please try again.';
}
}
}
?>
<h2>Add New Task</h2>
<?php if (!empty($errors)): ?>
<div class="error">
<ul>
<?php foreach($errors as $error): ?>
<li><?php echo htmlspecialchars($error); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if ($success): ?>
<div class="success">
<p><?php echo htmlspecialchars($success); ?></p>
</div>
<?php endif; ?>
<form action="add_task.php" method="POST">
<div class="form-group">
<label for="title">Task Title:</label>
<input type="text" id="title" name="title" value="<?php echo htmlspecialchars($title ?? ''); ?>" required>
</div>
<div class="form-group">
<label for="status">Status:</label>
<select id="status" name="status" required>
<option value="pending" <?php echo (isset($status) && $status === 'pending') ? 'selected' : ''; ?>>Pending</option>
<option value="completed" <?php echo (isset($status) && $status === 'completed') ? 'selected' : ''; ?>>Completed</option>
</select>
</div>
<button type="submit">Add Task</button>
</form>
<?php
require 'templates/footer.php';
?>
9. Editing Tasks (edit_task.php
)
This page allows users to edit existing tasks.
<?php
// edit_task.php
require 'config/db.php';
require 'templates/header.php';
$errors = [];
$success = '';
// Get task ID from URL
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
// Fetch existing task
$stmt = $pdo->prepare('SELECT * FROM tasks WHERE id = ?');
$stmt->execute([$id]);
$task = $stmt->fetch();
if (!$task) {
echo "<p>Task not found.</p>";
require 'templates/footer.php';
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Sanitize and validate input
$title = trim($_POST['title']);
$status = trim($_POST['status']);
if (empty($title)) {
$errors[] = 'Task title is required.';
}
if (empty($status)) {
$errors[] = 'Task status is required.';
} elseif (!in_array($status, ['pending', 'completed'])) {
$errors[] = 'Invalid task status.';
}
if (empty($errors)) {
// Update in database
$stmt = $pdo->prepare('UPDATE tasks SET title = ?, status = ? WHERE id = ?');
if ($stmt->execute([$title, $status, $id])) {
$success = 'Task updated successfully.';
// Refresh task data
$stmt = $pdo->prepare('SELECT * FROM tasks WHERE id = ?');
$stmt->execute([$id]);
$task = $stmt->fetch();
} else {
$errors[] = 'There was an error updating the task. Please try again.';
}
}
}
?>
<h2>Edit Task</h2>
<?php if (!empty($errors)): ?>
<div class="error">
<ul>
<?php foreach($errors as $error): ?>
<li><?php echo htmlspecialchars($error); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if ($success): ?>
<div class="success">
<p><?php echo htmlspecialchars($success); ?></p>
</div>
<?php endif; ?>
<form action="edit_task.php?id=<?php echo $id; ?>" method="POST">
<div class="form-group">
<label for="title">Task Title:</label>
<input type="text" id="title" name="title" value="<?php echo htmlspecialchars($task['title']); ?>" required>
</div>
<div class="form-group">
<label for="status">Status:</label>
<select id="status" name="status" required>
<option value="pending" <?php echo ($task['status'] === 'pending') ? 'selected' : ''; ?>>Pending</option>
<option value="completed" <?php echo ($task['status'] === 'completed') ? 'selected' : ''; ?>>Completed</option>
</select>
</div>
<button type="submit">Update Task</button>
</form>
<?php
require 'templates/footer.php';
?>
10. Deleting Tasks (delete_task.php
)
This script handles the deletion of tasks.
<?php
// delete_task.php
require 'config/db.php';
// Get task ID from URL
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
// Delete task
$stmt = $pdo->prepare('DELETE FROM tasks WHERE id = ?');
$stmt->execute([$id]);
// Redirect back to home page
header('Location: index.php');
exit;
?>
11. Testing the Application
- Access the Application:
- Navigate to
http://localhost/todo-app/index.php
in your browser.
- Navigate to
- Add a New Task:
- Click on “Add Task”.
- Fill in the task details and submit.
- Verify that the task appears on the home page.
- Edit a Task:
- Click on “Edit” next to a task.
- Modify the details and submit.
- Ensure the changes are reflected on the home page.
- Delete a Task:
- Click on “Delete” next to a task.
- Confirm the deletion.
- Verify that the task is removed from the list.
12. Deployment Considerations
When deploying to a live server:
- Secure Database Credentials: Use environment variables or secure configuration methods.
- Use HTTPS: Ensure your website uses HTTPS for encrypted data transmission.
- Regular Backups: Implement regular backups of your database and files.
- Error Reporting: Disable detailed error messages in production to prevent information leakage.
// In production, set error reporting to minimal ini_set('display_errors', 0); ini_set('log_errors', 1);
- Update Dependencies: Keep PHP and all libraries updated to their latest versions to patch security vulnerabilities.