Курс — «Программирование на PHP8 для начинающих» — #31 Практический проект. Интеграция всех изученных концепций
Здравствуйте, дорогие друзья.
В этом разделе мы интегрируем все изученные концепции в наше простое веб-приложение для управления списком задач (To-Do List). Мы добавим обработку сессий, использование базы данных, отладку и тестирование кода, а также обеспечим безопасность приложения.
Структура проекта
Обновим структуру проекта, чтобы включить новые файлы и папки:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
todo-app/ ├── index.php ├── add.php ├── edit.php ├── delete.php ├── login.php ├── logout.php ├── styles.css ├── config.php ├── database.php ├── Task.php ├── TaskController.php └── tests/ └── TaskControllerTest.php |
Настройка базы данных
Создадим файл config.php
для хранения конфигурации базы данных.
1 2 3 4 5 6 7 |
<!-- config.php --> <?php define('DB_HOST', 'localhost'); define('DB_NAME', 'todo_app'); define('DB_USER', 'root'); define('DB_PASS', ''); ?> |
Создадим файл database.php
для подключения к базе данных.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<!-- database.php --> <?php require 'config.php'; class Database { private $pdo; public function __construct() { try { $this->pdo = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASS); $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { die("Database connection failed: " . $e->getMessage()); } } public function getConnection() { return $this->pdo; } } ?> |
Создание модели задачи
Создадим файл Task.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 |
<!-- Task.php --> <?php class Task { private $id; private $name; public function __construct($id = null, $name = '') { $this->id = $id; $this->name = $name; } public function getId() { return $this->id; } public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } } ?> |
Создание контроллера задачи
Создадим файл TaskController.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 |
<!-- TaskController.php --> <?php require 'database.php'; require 'Task.php'; class TaskController { private $db; public function __construct() { $database = new Database(); $this->db = $database->getConnection(); } public function getAllTasks() { $stmt = $this->db->query("SELECT * FROM tasks"); return $stmt->fetchAll(PDO::FETCH_ASSOC); } public function getTaskById($id) { $stmt = $this->db->prepare("SELECT * FROM tasks WHERE id = ?"); $stmt->execute([$id]); return $stmt->fetch(PDO::FETCH_ASSOC); } public function addTask($name) { $stmt = $this->db->prepare("INSERT INTO tasks (name) VALUES (?)"); $stmt->execute([$name]); } public function updateTask($id, $name) { $stmt = $this->db->prepare("UPDATE tasks SET name = ? WHERE id = ?"); $stmt->execute([$name, $id]); } public function deleteTask($id) { $stmt = $this->db->prepare("DELETE FROM tasks WHERE id = ?"); $stmt->execute([$id]); } } ?> |
Обновление основных файлов
Обновим файлы index.php
, add.php
, edit.php
и delete.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 |
<!-- index.php --> <?php session_start(); require 'TaskController.php'; $taskController = new TaskController(); $tasks = $taskController->getAllTasks(); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>To-Do List</title> <link rel="stylesheet" href="styles.css"> </head> <body> <h1>To-Do List</h1> <?php if (!isset($_SESSION['user'])): ?> <a href="login.php">Login</a> <?php else: ?> <a href="logout.php">Logout</a> <?php endif; ?> <form action="add.php" method="post"> <input type="text" name="task" placeholder="New task" required> <button type="submit">Add Task</button> </form> <ul id="task-list"> <?php foreach ($tasks as $task): ?> <li><?php echo $task['name']; ?> <a href='edit.php?id=<?php echo $task['id']; ?>'>Edit</a> <a href='delete.php?id=<?php echo $task['id']; ?>'>Delete</a></li> <?php endforeach; ?> </ul> </body> </html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<!-- add.php --> <?php session_start(); require 'TaskController.php'; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SESSION['user'])) { $taskName = $_POST['task']; $taskController = new TaskController(); $taskController->addTask($taskName); header('Location: index.php'); } else { header('Location: login.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 |
<!-- edit.php --> <?php session_start(); require 'TaskController.php'; $taskController = new TaskController(); if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['id']) && isset($_SESSION['user'])) { $taskId = $_GET['id']; $task = $taskController->getTaskById($taskId); if ($task) { echo "<form action='edit.php' method='post'> <input type='hidden' name='id' value='{$task['id']}'> <input type='text' name='task' value='{$task['name']}' required> <button type='submit'>Save</button> </form>"; } else { echo "Task not found."; } } elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SESSION['user'])) { $taskId = $_POST['id']; $taskName = $_POST['task']; $taskController->updateTask($taskId, $taskName); header('Location: index.php'); } else { header('Location: login.php'); } ?> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<!-- delete.php --> <?php session_start(); require 'TaskController.php'; if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['id']) && isset($_SESSION['user'])) { $taskId = $_GET['id']; $taskController = new TaskController(); $taskController->deleteTask($taskId); header('Location: index.php'); } else { header('Location: login.php'); } ?> |
Добавление аутентификации
Создадим файлы login.php
и logout.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 |
<!-- login.php --> <?php session_start(); if ($_SERVER['REQUEST_METHOD'] === 'POST') { $username = $_POST['username']; $password = $_POST['password']; if ($username === 'admin' && $password === 'admin') { $_SESSION['user'] = $username; header('Location: index.php'); } else { $error = "Invalid username or password."; } } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Login</title> <link rel="stylesheet" href="styles.css"> </head> <body> <h1>Login</h1> <?php if (isset($error)): ?> <p><?php echo $error; ?></p> <?php endif; ?> <form action="login.php" method="post"> <input type="text" name="username" placeholder="Username" required> <input type="password" name="password" placeholder="Password" required> <button type="submit">Login</button> </form> </body> </html> |
1 2 3 4 5 6 |
<!-- logout.php --> <?php session_start(); session_destroy(); header('Location: index.php'); ?> |
Тестирование кода
Создадим тесты для контроллера задачи с использованием PHPUnit. Установим PHPUnit, как описано в предыдущих главах, и создадим файл TaskControllerTest.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 |
<!-- tests/TaskControllerTest.php --> <?php use PHPUnit\Framework\TestCase; require '../TaskController.php'; class TaskControllerTest extends TestCase { private $taskController; protected function setUp(): void { $this->taskController = new TaskController(); } public function testAddTask() { $this->taskController->addTask('Test Task'); $tasks = $this->taskController->getAllTasks(); $this->assertContains('Test Task', array_column($tasks, 'name')); } public function testUpdateTask() { $this->taskController->addTask('Test Task'); $tasks = $this->taskController->getAllTasks(); $taskId = end($tasks)['id']; $this->taskController->updateTask($taskId, 'Updated Task'); $updatedTask = $this->taskController->getTaskById($taskId); $this->assertEquals('Updated Task', $updatedTask['name']); } public function testDeleteTask() { $this->taskController->addTask('Test Task'); $tasks = $this->taskController->getAllTasks(); $taskId = end($tasks)['id']; $this->taskController->deleteTask($taskId); $tasks = $this->taskController->getAllTasks(); $this->assertNotContains('Test Task', array_column($tasks, 'name')); } } ?> |
Мы интегрировали все изученные концепции в наше простое веб-приложение для управления списком задач. Мы добавили обработку сессий для аутентификации пользователей, использовали базу данных для хранения данных, написали тесты с использованием PHPUnit и обеспечили безопасность приложения. Этот проект демонстрирует, как можно использовать PHP для создания полноценных веб-приложений, интегрируя различные технологии и подходы. В следующем разделе мы рассмотрим, как развернуть наше приложение на сервере.

На этом все. Всем хорошего дня!
Цикл статей по курсу — «Программирование на PHP8 для начинающих».