1
0
Files
nure/semester-4/СмП/lb-3/Лр_3_Ситник_ПЗПІ_23_2.txt
Sytnyk Yehor d22b7ddcaf SMP all works
2025-06-05 12:21:37 +03:00

786 lines
31 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
ХАРКІВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ РАДІОЕЛЕКТРОНІКИ
Кафедра Програмної інженерії
Звіт
з лабораторної роботи №3
з дисципліни: «Скриптові мови програмування»
з теми: « Створення WEB-застосунків за допомогою PHP «
Виконав: Перевірив:
ст. гр. ПЗПІ-23-2 Старший викладач кафедри ПІ
Ситник Є. С. Сокорчук І. П.
Харків 2025
2
3 СТВОРЕННЯ WEB-ЗАСТОСУНКІВ ЗА ДОПОМОГОЮ PHP
3.1 Історія змін
№ Дата Версія звіту Опис змін та виправлень
1 03.06.2025 0.1 Створено звіт
3.2 Мета роботи
Лабораторна робота полягає у розробці веб-застосунку «Продовольчий
магазин Весна» засобами мови програмування PHP з використанням HTML, CSS та
JavaScript для створення інтерактивного інтерфейсу користувача.
3.3 Хід роботи
3.3.1 Архітектура веб-застосунку
Для реалізації веб-застосунку було обрано модульний підхід з розділенням
логіки на окремі файли:
3.3.1.1 Структура файлів:
index.php головна сторінка застосунку з логотипом магазину;
items.php сторінка каталогу товарів з можливістю додавання до кошика;
cart.php сторінка кошика з переглядом обраних товарів та управлінням;
handle_cart.php обробник AJAX-запитів для роботи з кошиком;
DB.php клас для роботи з базою даних SQLite;
style.css стилі для оформлення веб-сторінок.
3.3.1.2 Основні компоненти:
Клас DB забезпечує взаємодію з базою даних SQLite, включаючи
методи для роботи з товарами, кошиком та налаштуваннями користувача;
Клас DbException спеціалізований виняток для обробки помилок бази
даних;
Сесійна система для збереження стану користувача між сторінками.
3
3.3.2 Структура бази даних
Веб-застосунок використовує базу даних SQLite з трьома основними
таблицями:
3.3.2.1 Таблиця settings:
name (TEXT) ім’я користувача;
age (TEXT) вік користувача.
3.3.2.2 Таблиця items:
id (INTEGER PRIMARY KEY) унікальний ідентифікатор товару;
name (TEXT NOT NULL) назва товару;
price (REAL NOT NULL) ціна товару.
3.3.2.3 Таблиця cart:
id (INTEGER NOT NULL UNIQUE) ідентифікатор товару;
count (INTEGER NOT NULL) кількість товару в кошику;
FOREIGN KEY зв’язок з таблицею items.
3.3.3 Функціональні можливості
3.3.3.1 Головна сторінка (index.php):
Відображення логотипу магазину;
Навігаційне меню з кількістю товарів у кошику;
Привітання користувача за ім’ям;
Підвал з інформацією про магазин.
3.3.3.2 Каталог товарів (items.php):
Відображення списку доступних товарів з цінами;
Форма для вибору кількості товару;
Можливість додавання товарів до кошика;
Валідація кількості товару (від 0 до 100 одиниць);
4
Автоматичне оновлення лічильника кошика.
3.3.3.3 Кошик покупок (cart.php):
Перегляд обраних товарів з детальною інформацією;
Відображення кількості, ціни за одиницю та загальної вартості;
Можливість видалення окремих товарів з кошика;
Функція повного очищення кошика;
Підрахунок загальної суми покупки;
Кнопка «Сплатити» для завершення покупки.
3.3.3.4 Обробка запитів (handle_cart.php):
Обробка POST-запитів для додавання товарів до кошика;
Обробка DELETE-запитів для видалення товарів;
Підтримка AJAX для асинхронного оновлення кошика;
Валідація вхідних даних та обробка помилок.
3.3.4 Технічні особливості
3.3.4.1 Безпека:
Використання підготовлених запитів (prepared statements) для запобігання
SQL-ін’єкціям;
Функція «htmlspecialchars()» для запобігання XSS-атакам;
Валідація та фільтрація користувацьких даних через «filter_input()»;
Обробка винятків для коректної роботи з помилками.
3.3.4.2 Користувацький інтерфейс:
Адаптивний дизайн з використанням CSS;
Інтуїтивна навігація між сторінками;
Зручні форми для взаємодії з користувачем.
5
3.3.4.3 База даних:
Автоматичне створення таблиць при першому запуску;
Заповнення початковими даними;
3.3.5 Методи класу DB
Клас DB містить наступні основні методи:
retrieve_user() отримання інформації про користувача;
update_user() оновлення профілю користувача;
get_items() отримання списку всіх товарів;
get_item_by_id() отримання конкретного товару за ID;
get_cart() отримання товарів у кошику з детальною інформацією;
get_cart_count() підрахунок загальної кількості товарів у кошику;
get_cart_total() підрахунок загальної вартості кошика;
add_to_cart() додавання товару до кошика або оновлення кількості;
remove_from_cart() видалення товару з кошика;
empty_cart() повне очищення кошика.
3.4 Висновки
Під час виконання даної лабораторної роботи було успішно розроблено веб-
застосунок інтернет-магазину з використанням сучасних веб-технологій. Зокрема,
було освоєно:
створення багатосторінкових веб-застосунків на PHP;
роботу з базами даних SQLite через PDO з дотриманням принципів
безпеки;
реалізацію сесійної системи для збереження стану користувача;
створення інтерактивного користувацького інтерфейсу з використанням
HTML та CSS;
валідацію та фільтрацію користувацьких даних.
Застосунок демонструє практичне застосування технологій веб-розробки для
створення реальних рішень.
6
ДОДАТОК А
Відеозапис
Відеозапис презентації результатів лабораторної роботи: https://youtu.be/Gils7poMkgk
Хронологічний опис відеозапису:
00:00 Вступ та загальний опис роботи
00:30 Структура веб-застосунку
01:14 Робота з базою даних та сесіями
01:43 Обробка запитів користувача
03:56 Демонстрація роботи веб-застосунку
7
ДОДАТОК Б
Програмний код
Б.1 Головна сторінка (index.php)
GitHub репозиторій: https://github.com/NureSytnykYehor/smp-pzpi-23-2-sytnyk-yehor/blob/main/Lab3/smp-pzpi-23-2-sytnyk-yehor-lab3/index.php
1 <?php
2 session_start();
3 require_once 'DB.php';
4
5 $db = new DB('shop.db');
6
7 if (!isset($_SESSION['user'])) {
8 $_SESSION['user'] = $db->retrieve_user();
9 }
10
11 $cart_count = $db->get_cart_count();
12 ?>
13
14 <!DOCTYPE html>
15 <html lang="uk">
16 <head>
17 <meta charset="UTF-8">
18 <title>Головна сторінка</title>
19 <link rel="stylesheet" href="style.css">
20 </head>
21 <body>
22 <header>
23 <h1>Продовольчий магазин "Весна"</h1>
24 <h3> Добрий день <?php echo $_SESSION['user']['name'] ?> </h3>
25 <nav>
26 <a href="index.php">Головна</a>
27 |
28 <a href="items.php">Товари</a>
29 |
30 <a href="cart.php">Кошик (<?php echo $cart_count ?? 0; ?
>)</a>
31 </nav>
32 </header>
33
34 <div class="container" style="display: flex; flex-direction:
column; align-items: center;">
35 <img src="logo.png" alt="logo" style="width: 90%;">
36 </div>
37
38 <footer>
39 <nav>
40 <a href="index.php">Головна</a>
41 |
42 <a href="items.php">Товари</a>
43 |
8
44 <a href="cart.php">Кошик (<?php echo $cart_count ?? 0; ?
>)</a>
45 </nav>
46 <p>&copy; <?php echo date("Y"); ?> ТОВ "Весна". Усі права
захищені.</p>
47 </footer>
48 </body>
49 </html>
Б.2 Каталог товарів (items.php)
GitHub репозиторій: https://github.com/NureSytnykYehor/smp-pzpi-23-2-sytnyk-yehor/blob/main/Lab3/smp-pzpi-23-2-sytnyk-yehor-lab3/items.php
1 <?php
2 session_start();
3 require_once 'DB.php';
4
5 $db = new DB('shop.db');
6
7 if (!isset($_SESSION['user'])) {
8 $_SESSION['user'] = $db->retrieve_user();
9 }
10
11 $items = $db->get_items();
12 $cart_count = $db->get_cart_count();
13 ?>
14
15 <!DOCTYPE html>
16 <html lang="uk">
17 <head>
18 <meta charset="UTF-8">
19 <title>Сторінка товарів</title>
20 <link rel="stylesheet" href="style.css">
21 </head>
22 <body>
23 <header>
24 <h1>Продовольчий магазин "Весна"</h1>
25 <h3> Добрий день <?php echo $_SESSION['user']['name'] ?> </h3>
26 <nav>
27 <a href="index.php">Головна</a>
28 |
29 <a href="items.php">Товари</a>
30 |
31 <a href="cart.php">Кошик (<?php echo $cart_count ?? 0; ?
>)</a>
32 </nav>
33 </header>
34
35 <div class="container">
36 <h2>Доступні товари</h2>
37 <div class="product-list">
38 <?php foreach ($items as $item): ?>
39 <div>
9
40 <h2><?php echo htmlspecialchars($item['name']); ?
></h2>
41 <h3>Ціна: <?php echo number_format($item['price'],
2); ?> грн</h3>
42
43 <form action="handle_cart.php" method="POST">
44 <input type="hidden" name="product_id"
value="<?php echo htmlspecialchars($item['id']); ?>">
45 <label for="quantity_<?php echo
htmlspecialchars($item['id']); ?>">Кількість:</label>
46 <input type="number" id="quantity_<?php echo
htmlspecialchars($item['id']); ?>" name="quantity" value="0" min="0"
max="100">
47 <button type="submit">Купити</button>
48 </form>
49 </div>
50 <?php endforeach; ?>
51 </div>
52 </div>
53
54 <footer>
55 <nav>
56 <a href="index.php">Головна</a>
57 |
58 <a href="items.php">Товари</a>
59 |
60 <a href="cart.php">Кошик (<?php echo $cart_count ?? 0; ?
>)</a>
61 </nav>
62 <p>&copy; <?php echo date("Y"); ?> ТОВ "Весна". Усі права
захищені.</p>
63 </footer>
64 </body>
65 </html>
Б.3 Кошик покупок (cart.php)
GitHub репозиторій: https://github.com/NureSytnykYehor/smp-pzpi-23-2-sytnyk-yehor/blob/main/Lab3/smp-pzpi-23-2-sytnyk-yehor-lab3/cart.php
1 <?php
2 session_start();
3 require_once 'DB.php';
4
5 $db = new DB("shop.db");
6
7 if (!isset($_SESSION['user'])) {
8 $_SESSION['user'] = $db->retrieve_user();
9 }
10
11 $cart_items = $db->get_cart();
12 $cart_total = $db->get_cart_total();
13 $cart_count = $db->get_cart_count();
14 ?>
10
15
16 <!DOCTYPE html>
17 <html lang="uk">
18 <head>
19 <meta charset="UTF-8">
20 <title>Кошик</title>
21 <link rel="stylesheet" href="style.css">
22 </head>
23 <body>
24 <header>
25 <h1>Продовольчий магазин "Весна"</h1>
26 <h3> Добрий день <?php echo $_SESSION['user']['name'] ?> </h3>
27 <nav>
28 <a href="index.php">Головна</a>
29 |
30 <a href="items.php">Товари</a>
31 |
32 <a href="cart.php">Кошик (<?php echo $cart_count ?? 0; ?
>)</a>
33 </nav>
34 </header>
35
36 <div class="container">
37 <?php if (empty($cart_items)): ?>
38 <div style="display: flex; align-items: center; justify-
content: space-evenly;">
39 <h3>Ваш кошик порожній <a href="items.php">Перейти до
покупок</a> </h3>
40 </div>
41 <?php else: ?>
42 <div style="display: flex; align-items: center; justify-
content: space-evenly;">
43 <h3>Ваш кошик</h3>
44 <h3 class="cart-summary">
45 Загальна сума: <?php echo
number_format($cart_total, 2); ?> грн
46 </h3>
47
48 <button type="submit">Сплатити</button>
49
50 <button onclick="fetch('handle_cart.php', {'method':
'DELETE'}).then(_ => { location.reload(); });">Очистити</button>
51 </div>
52
53 <div class="product-list">
54 <?php foreach ($cart_items as $item): ?>
55 <div>
56 <h2>
57 <?php echo
htmlspecialchars($item['name']); ?>
58 <br>
59 <?php echo
htmlspecialchars($item['count']); ?> шт.
60 </h2>
61
11
62 <span>Ціна за одиницю: <?php echo
number_format($item['price'], 2); ?> грн</span>
63 <br>
64 <span>Загальна ціна: <?php echo
number_format($item['total_price'], 2); ?> грн</span>
65
66 <br><br>
67
68 <button
69 style="width: 100%;"
70 onclick="
71 fetch(
72 'handle_cart.php?product_id=<?php echo
htmlspecialchars($item['id']); ?>',
73 { 'method': 'DELETE' }
74 ).then(_ => { location.reload(); });">
75 Видалити
76 </button>
77 </div>
78 <?php endforeach; ?>
79 </div>
80 <?php endif; ?>
81 </div>
82
83 <footer>
84 <nav>
85 <a href="index.php">Головна</a>
86 |
87 <a href="items.php">Товари</a>
88 |
89 <a href="cart.php">Кошик (<?php echo $cart_count ?? 0; ?
>)</a>
90 </nav>
91 <p>&copy; <?php echo date("Y"); ?> ТОВ "Весна". Усі права
захищені.</p>
92 </footer>
93 </body>
94 </html>
Б.4 Обробник кошика (handle_cart.php)
GitHub репозиторій: https://github.com/NureSytnykYehor/smp-pzpi-23-2-sytnyk-yehor/blob/main/Lab3/smp-pzpi-23-2-sytnyk-yehor-lab3/handle_cart.php
1 <?php
2 session_start();
3 require_once 'DB.php';
4
5 $db_path = 'shop.db';
6 $db = new DB($db_path);
7
8 switch ($_SERVER['REQUEST_METHOD']) {
9 case 'POST':
12
10 $product_id = filter_input(INPUT_POST, 'product_id',
FILTER_VALIDATE_INT);
11 $quantity = filter_input(INPUT_POST, 'quantity',
FILTER_VALIDATE_INT);
12
13 if ($product_id !== false && $product_id !== null &&
$quantity !== false && $quantity !== null) {
14 try {
15 $db->add_to_cart($product_id, $quantity);
16 } catch (DbException $e) {
17 error_log("Cart handling error: " . $e->getMessage());
18 }
19 }
20 header('Location: items.php');
21 break;
22
23 case 'DELETE':
24 $product_id = filter_input(INPUT_GET, 'product_id',
FILTER_VALIDATE_INT);
25
26 if ($product_id === null) {
27 try {
28 $db->empty_cart();
29 } catch (DbException $e) {
30 error_log("Cart handling error: " . $e->getMessage());
31 }
32 } else if ($product_id !== false) {
33 try {
34 $db->remove_from_cart($product_id);
35 } catch (DbException $e) {
36 error_log("Cart handling error: " . $e->getMessage());
37 }
38 }
39
40 header('Location: cart.php');
41 break;
42
43 default:
44 break;
45 }
46
47 exit();
Б.5 Клас для роботи з базою даних (DB.php)
GitHub репозиторій: https://github.com/NureSytnykYehor/smp-pzpi-23-2-sytnyk-yehor/blob/main/Lab3/smp-pzpi-23-2-sytnyk-yehor-lab3/DB.php
1 <?php
2
3 class DbException extends Exception {}
4
5 class DB
6 {
13
7 private $pdo;
8
9 /**
10 * Initializes database
11 *
12 * @param string $db_path
13 * @throws DbException If there's a database error.
14 */
15 public function __construct($db_path)
16 {
17 try {
18 $this->pdo = new PDO("sqlite:" . $db_path);
19 $this->pdo->setAttribute(PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION);
20 } catch (PDOException $e) {
21 throw new DbException("Connection to DB failed.\nCaused
by: " . $e->getMessage());
22 }
23
24 // Ініціалізація таблиць та початкових даних
25 try {
26 $this->pdo->exec("
27 CREATE TABLE IF NOT EXISTS settings (
28 name TEXT,
29 age TEXT
30 );
31 ");
32 if ($this->pdo->query("SELECT COUNT(*) FROM settings;")-
>fetchColumn() == 0) {
33 $this->pdo->exec("INSERT INTO settings (name, age)
VALUES ('user', 0);");
34 }
35 } catch (PDOException $e) {
36 throw new DbException("Error initialising settings table.
\nCaused by: " . $e->getMessage());
37 }
38
39 try {
40 $this->pdo->exec("
41 CREATE TABLE IF NOT EXISTS items (
42 id INTEGER PRIMARY KEY AUTOINCREMENT,
43 name TEXT NOT NULL,
44 price REAL NOT NULL
45 );
46 ");
47 if ($this->pdo->query("SELECT COUNT(id) FROM items;")-
>fetchColumn() == 0) {
48 $this->pdo->exec("
49 INSERT INTO items (name, price) VALUES ('Молоко
пастеризоване', 32.50);
50 INSERT INTO items (name, price) VALUES ('Хліб
чорний', 18.00);
51 INSERT INTO items (name, price) VALUES ('Сир
білий', 85.00);
52 INSERT INTO items (name, price) VALUES ('Сметана
20%', 45.80);
14
53 INSERT INTO items (name, price) VALUES ('Кефір
1%', 28.50);
54 INSERT INTO items (name, price) VALUES ('Вода
газована', 25.00);
55 INSERT INTO items (name, price) VALUES ('Печиво
\"Весна\"', 42.30);
56 INSERT INTO items (name, price) VALUES ('Масло
вершкове', 125.00);
57 INSERT INTO items (name, price) VALUES ('Йогурт
натуральний', 38.90);
58 INSERT INTO items (name, price) VALUES ('Сік
апельсиновий', 55.00);
59 ");
60 }
61 } catch (PDOException $e) {
62 throw new DbException("Error initialising items table.
\nCaused by: " . $e->getMessage());
63 }
64
65 try {
66 $this->pdo->exec("
67 CREATE TABLE IF NOT EXISTS cart (
68 id INTEGER NOT NULL UNIQUE,
69 count INTEGER NOT NULL,
70 FOREIGN KEY(id) REFERENCES items(id) ON DELETE
CASCADE
71 );
72 ");
73 } catch (PDOException $e) {
74 throw new DbException("Error initialising cart table.
\nCaused by: " . $e->getMessage());
75 }
76 }
77
78 /**
79 * Retrieve user information from the database
80 *
81 * @return array
82 * @throws DbException If there's a database error.
83 */
84 public function retrieve_user(): array
85 {
86 try {
87 $stmt = $this->pdo->query("SELECT name, age FROM
settings;");
88 return $stmt->fetch(PDO::FETCH_ASSOC);
89 } catch (PDOException $e) {
90 throw new DbException("Error retrieving user info.\nCaused
by: " . $e->getMessage());
91 }
92 }
93
94 /**
95 * Fetches all items from the database.
96 *
97 * @return array[]
15
98 * @throws DbException If there's a database error.
99 */
100 public function get_items(): array
101 {
102 try {
103 $stmt = $this->pdo->query("SELECT id, name, price FROM
items ORDER BY id;");
104 return $stmt->fetchAll(PDO::FETCH_ASSOC);
105 } catch (PDOException $e) {
106 throw new DbException("Error retrieving data from the
items table.\nCaused by: " . $e->getMessage());
107 }
108 }
109
110 /**
111 * Fetches all items in the cart from the database.
112 *
113 * @return array[]
114 * @throws DbException If there's a database error.
115 */
116 public function get_cart(): array
117 {
118 try {
119 $stmt = $this->pdo->query(
120 "SELECT
121 cart.id,
122 items.name,
123 items.price,
124 cart.count,
125 ROUND(items.price * cart.count, 2) as total_price
126 FROM cart
127 INNER JOIN items ON cart.id = items.id
128 ORDER BY cart.id;"
129 );
130 return $stmt->fetchAll(PDO::FETCH_ASSOC);
131 } catch (PDOException $e) {
132 throw new DbException("Error retrieving cart items.
\nCaused by: " . $e->getMessage());
133 }
134 }
135
136 /**
137 * Get total items count in cart
138 *
139 * @return int
140 * @throws DbException If there's a database error.
141 */
142 public function get_cart_count(): int
143 {
144 try {
145 $stmt = $this->pdo->query("SELECT COALESCE(SUM(count), 0)
FROM cart;");
146 return (int)$stmt->fetchColumn();
147 } catch (PDOException $e) {
148 throw new DbException("Error getting cart count.\nCaused
by: " . $e->getMessage());
16
149 }
150 }
151
152 /**
153 * Get total price of all items in cart
154 *
155 * @return float
156 * @throws DbException If there's a database error.
157 */
158 public function get_cart_total(): float
159 {
160 try {
161 $stmt = $this->pdo->query(
162 "SELECT COALESCE(SUM(items.price * cart.count), 0.0)
163 FROM cart
164 INNER JOIN items ON cart.id = items.id;"
165 );
166 return (float)$stmt->fetchColumn();
167 } catch (PDOException $e) {
168 throw new DbException("Error calculating cart total.
\nCaused by: " . $e->getMessage());
169 }
170 }
171
172 /**
173 * Add item to the cart or update its quantity.
174 *
175 * @param int $id
176 * @param int $count
177 *
178 * @return bool
179 * @throws DbException If there's a database error or item doesn't
exist.
180 */
181 public function add_to_cart($id, $count): bool
182 {
183 try {
184 // Check if the item exists
185 $item = $this->get_item_by_id($id);
186 if (!$item) {
187 throw new DbException("Item with ID $id does not
exist.");
188 }
189
190 // If count is 0 or less, remove the item from the cart
191 if ($count <= 0) {
192 return $this->remove_from_cart($id);
193 }
194
195 // Insert or update the cart item
196 $stmt = $this->pdo->prepare(
197 "INSERT INTO cart (id, count)
198 VALUES (:id, :count)
199 ON CONFLICT(id) DO UPDATE SET
200 count = excluded.count;"
201 );
17
202 return $stmt->execute(['id' => $id, 'count' => $count]);
203 } catch (PDOException $e) {
204 throw new DbException("Error adding/updating item in the
cart.\nCaused by: " . $e->getMessage());
205 }
206 }
207
208 /**
209 * Empty the cart
210 *
211 * @return bool
212 * @throws DbException If there's a database error.
213 */
214 public function empty_cart(): bool
215 {
216 try {
217 $stmt = $this->pdo->prepare("DELETE FROM cart");
218 return $stmt->execute();
219 } catch (PDOException $e) {
220 throw new DbException("Error removing item from the cart.
\nCaused by: " . $e->getMessage());
221 }
222 }
223
224 /**
225 * Remove an item from the cart
226 *
227 * @param int $id
228 *
229 * @return bool
230 * @throws DbException If there's a database error.
231 */
232 public function remove_from_cart($id): bool
233 {
234 try {
235 $stmt = $this->pdo->prepare("DELETE FROM cart WHERE id
= :id");
236 return $stmt->execute(['id' => $id]);
237 } catch (PDOException $e) {
238 throw new DbException("Error removing item from the cart.
\nCaused by: " . $e->getMessage());
239 }
240 }
241 }