Files
web_work/README.md
kirill.khorkov 474fe41d41 ADD
2025-12-16 03:17:36 +03:00

1208 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
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.
# AETERNA - Интернет-магазин мебели и интерьера
```
___ ________________ _ _____
/ | / ____/_ __/ __ \/ | / / |
/ /| | / __/ / / / /_/ / |/ / /| |
/ ___ |/ /___ / / / _, _/ /| / ___ |
/_/ |_/_____/ /_/ /_/ |_/_/ |_/_/ |_|
```
---
## Оглавление
- [Возможности](#возможности)
- [Технологический стек](#технологический-стек)
- [Структура проекта](#структура-проекта)
- [База данных](#база-данных)
- [Установка и настройка](#установка-и-настройка)
- [Запуск проекта](#запуск-проекта)
- [Аутентификация и авторизация](#аутентификация-и-авторизация)
- [Функционал](#функционал)
- [API Endpoints](#api-endpoints)
- [Административная панель](#административная-панель)
- [Функции и утилиты](#функции-и-утилиты)
- [Безопасность](#безопасность)
- [Тестовые аккаунты](#тестовые-аккаунты)
- [Разработка](#разработка)
---
## Возможности
### Для покупателей
- Просмотр каталога товаров с фильтрацией по категориям, цене, цвету и материалу
- Поиск товаров по названию
- Детальная страница товара с характеристиками
- Корзина покупок с возможностью изменения количества
- Оформление заказа с выбором способа доставки и оплаты
- Личный кабинет с историей заказов
- Регистрация и авторизация
### Для администраторов
- Полное управление каталогом товаров (CRUD)
- Управление категориями и подкатегориями
- Просмотр и обработка заказов
- Управление пользователями
- Статистика продаж
---
## Технологический стек
| Компонент | Технология |
|-----------|------------|
| Backend | PHP 7.4+ |
| База данных | PostgreSQL 12+ |
| Стилизация | LESS (компилируется в CSS) |
| JavaScript | jQuery 3.6+ |
| Иконки | Font Awesome 5.15 |
| ORM/DB | PDO (PHP Data Objects) |
### Зависимости
- PHP расширения: `pdo`, `pdo_pgsql`, `mbstring`, `json`
- Браузерная компиляция LESS (less.js)
---
## Структура проекта
```
cite_practica1/
├── admin/ # Административная панель
│ └── index.php # Главная страница админки
├── api/ # API endpoints (дублируются в public/api/)
│ ├── auth.php # Аутентификация пользователя
│ ├── add_to_cart.php # Добавление товара в корзину
│ ├── cart.php # Управление корзиной (add/update/remove/get/count)
│ ├── get_cart.php # Получение содержимого корзины
│ ├── get_cart_count.php # Количество товаров в корзине
│ ├── get_product.php # Получение информации о товаре
│ ├── process_order.php # Оформление заказа
│ ├── register_handler.php # Регистрация пользователя
│ └── update_cart.php # Обновление количества в корзине
├── assets/ # Статические ресурсы
│ ├── css/ # Скомпилированные CSS файлы
│ ├── img/ # Изображения товаров и интерфейса
│ ├── js/ # JavaScript файлы
│ │ ├── checkout.js # Логика оформления заказа
│ │ └── profile.js # Логика профиля пользователя
│ └── less/ # LESS исходники стилей
│ ├── style.less # Основные стили
│ ├── checkout.less # Стили страницы оформления
│ └── mixins.less # LESS миксины
├── config/ # Конфигурация
│ ├── database.php # Подключение к PostgreSQL
│ └── check_auth.js # Клиентская проверка авторизации
├── includes/ # Общие компоненты
│ ├── auth.php # Функции авторизации
│ ├── footer.php # Футер сайта
│ ├── functions.php # Вспомогательные функции
│ └── header.php # Шапка сайта
├── migrations/ # SQL миграции базы данных
│ ├── 001_initial_schema.sql # Начальная схема (users, categories, products)
│ ├── 002_add_cart_orders.sql # Корзина и заказы
│ ├── 003_add_product_fields.sql # Дополнительные поля товаров
│ ├── 004_grant_admin_to_admin_mail.sql # Права администратора
│ ├── grant_admin.php # Скрипт назначения админа
│ ├── migrate.php # Раннер миграций
│ └── seed_data.sql # Тестовые данные
├── public/ # Публичная директория (точка входа веб-сервера)
│ ├── index.php # Главная страница
│ ├── catalog.php # Каталог товаров
│ ├── product.php # Страница товара
│ ├── checkout.php # Оформление заказа / корзина
│ ├── login.php # Страница входа
│ ├── logout.php # Выход из аккаунта
│ ├── register.php # Регистрация
│ ├── services.php # Страница услуг
│ ├── delivery.php # Доставка и оплата
│ ├── warranty.php # Гарантия
│ ├── header_common.php # Общий header
│ ├── footer.php # Footer
│ ├── api/ # API endpoints
│ ├── config/ # Конфигурация
│ ├── includes/ # Общие компоненты
│ ├── img/ # Изображения
│ └── assets/ # Статические ресурсы
├── uploads/ # Загруженные файлы
│ └── products/ # Изображения товаров
├── setup.sh # Скрипт первоначальной настройки
├── style_for_cite.less # Основной файл стилей
└── README.md # Этот файл
```
---
## База данных
### Схема базы данных
```mermaid
erDiagram
users ||--o{ cart : has
users ||--o{ orders : places
categories ||--o{ products : contains
categories ||--o{ subcategories : has
products ||--o{ cart : added_to
products ||--o{ order_items : included_in
orders ||--|{ order_items : contains
users {
int user_id PK
varchar email UK
varchar password_hash
varchar full_name
varchar phone
varchar city
timestamp created_at
timestamp updated_at
timestamp last_login
boolean is_active
boolean is_admin
}
categories {
int category_id PK
varchar name
varchar slug UK
int parent_id FK
text description
int sort_order
boolean is_active
timestamp created_at
timestamp updated_at
}
subcategories {
int subcategory_id PK
int category_id FK
varchar name
varchar slug UK
text description
int sort_order
boolean is_active
timestamp created_at
}
products {
int product_id PK
int category_id FK
varchar name
varchar slug UK
text description
decimal price
decimal old_price
varchar sku UK
int stock_quantity
boolean is_available
boolean is_featured
decimal rating
int review_count
varchar image_url
varchar color
varchar material
varchar card_size
timestamp created_at
timestamp updated_at
}
cart {
int cart_id PK
int user_id FK
int product_id FK
int quantity
timestamp created_at
timestamp updated_at
}
orders {
int order_id PK
varchar order_number UK
int user_id FK
varchar customer_name
varchar customer_email
varchar customer_phone
text delivery_address
varchar delivery_region
varchar postal_code
varchar delivery_method
varchar payment_method
decimal subtotal
decimal discount_amount
decimal delivery_price
decimal final_amount
varchar promo_code
varchar status
text notes
timestamp created_at
timestamp updated_at
timestamp completed_at
}
order_items {
int item_id PK
int order_id FK
int product_id FK
varchar product_name
decimal product_price
int quantity
decimal total_price
timestamp created_at
}
```
### Описание таблиц
| Таблица | Описание |
|---------|----------|
| `users` | Пользователи системы (покупатели и администраторы) |
| `categories` | Категории товаров (Диваны, Кресла, Кровати и т.д.) |
| `subcategories` | Подкатегории для более детальной классификации |
| `products` | Товары с ценами, описанием и характеристиками |
| `cart` | Корзина покупок (связь пользователь-товар-количество) |
| `orders` | Заказы с информацией о доставке и оплате |
| `order_items` | Позиции заказа (товары в заказе) |
| `migrations` | Служебная таблица для отслеживания миграций |
### Миграции
Миграции выполняются в следующем порядке:
1. `001_initial_schema.sql` - Создание таблиц users, categories, subcategories, products
2. `002_add_cart_orders.sql` - Добавление таблиц cart, orders, order_items
3. `003_add_product_fields.sql` - Дополнительные поля для товаров (color, material, card_size)
4. `004_grant_admin_to_admin_mail.sql` - Назначение прав администратора
---
## Установка и настройка
### Требования
- PHP 7.4 или выше
- PostgreSQL 12 или выше
- Веб-сервер (Apache) или встроенный PHP сервер для разработки
### Шаг 1: Клонирование репозитория
```bash
git clone <repository-url>
cd cite_practica1
```
### Шаг 2: Настройка базы данных
Отредактируйте файл `config/database.php`:
```php
<?php
class Database {
private static $instance = null;
private $connection;
private function __construct() {
try {
$this->connection = new PDO(
"pgsql:host=ВАШ_ХОСТ;port=5432;dbname=ВАШ_DBNAME",
"ВАШ_ЛОГИН",
"ВАШ_ПАРОЛЬ"
);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->connection->exec("SET NAMES 'utf8'");
} catch(PDOException $e) {
die("Ошибка подключения: " . $e->getMessage());
}
}
public static function getInstance() {
if (self::$instance == null) {
self::$instance = new Database();
}
return self::$instance;
}
public function getConnection() {
return $this->connection;
}
}
```
### Шаг 3: Запуск миграций
**Вариант 1: Автоматическая настройка**
```bash
chmod +x setup.sh
./setup.sh
```
**Вариант 2: Ручной запуск миграций**
```bash
php migrations/migrate.php
```
**Вариант 3: Загрузка тестовых данных**
```bash
php migrations/migrate.php --seed
```
### Шаг 4: Настройка прав доступа
```bash
chmod -R 755 public/
chmod -R 777 uploads/
```
---
## Запуск проекта
### Разработка (встроенный PHP сервер)
```bash
cd public
php -S localhost:8000
```
Затем откройте в браузере: http://localhost:8000
### Production (Apache)
Пример конфигурации Virtual Host:
```apache
<VirtualHost *:80>
ServerName aeterna.local
DocumentRoot /path/to/cite_practica1/public
<Directory /path/to/cite_practica1/public>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/aeterna_error.log
CustomLog ${APACHE_LOG_DIR}/aeterna_access.log combined
</VirtualHost>
```
## Аутентификация и авторизация
### Архитектура аутентификации
```mermaid
flowchart TD
A[Пользователь] --> B{Авторизован?}
B -->|Нет| C[Страница входа]
B -->|Да| D{Роль?}
C --> E[Ввод email/пароль]
E --> F[API: auth.php]
F --> G{Проверка в БД}
G -->|Успех| H[Создание сессии]
G -->|Ошибка| I[Сообщение об ошибке]
H --> J[Сохранение в SESSION]
J --> K[Редирект на каталог]
D -->|Пользователь| L[Доступ к каталогу, корзине, заказам]
D -->|Админ| M[Доступ к админ-панели]
```
### Система сессий
При успешной авторизации в сессию сохраняются:
```php
$_SESSION['user_id'] // ID пользователя
$_SESSION['user_email'] // Email
$_SESSION['full_name'] // Полное имя
$_SESSION['isLoggedIn'] // true
$_SESSION['isAdmin'] // true/false
$_SESSION['login_time'] // Время входа
```
### Защита страниц
```php
// Требовать авторизацию
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
header('Location: login.php?error=auth_required');
exit();
}
// Требовать права администратора
if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) {
header('Location: login.php?error=admin_required');
exit();
}
```
### Роли пользователей
| Роль | Доступ |
|------|--------|
| Гость | Главная страница, услуги, доставка, гарантия |
| Пользователь | + Каталог, корзина, оформление заказов, личный кабинет |
| Администратор | + Админ-панель, управление товарами, заказами, пользователями |
---
## Функционал
### Пользовательский интерфейс
```mermaid
flowchart LR
subgraph pages [Страницы]
A[Главная] --> B[Каталог]
B --> C[Товар]
C --> D[Корзина]
D --> E[Оформление]
E --> F[Успех]
end
subgraph auth [Авторизация]
G[Вход] --> H[Регистрация]
end
subgraph info [Информация]
I[Услуги]
J[Доставка]
K[Гарантия]
L[Контакты]
end
```
#### Главная страница (`public/index.php`)
- Hero-секция с призывом к действию
- Преимущества компании
- Промо-блоки с акциями
- Секция "О нас"
- Слайдер с готовыми решениями
- Статистика компании
- FAQ (частые вопросы)
#### Каталог товаров (`public/catalog.php`)
- Сетка товаров с изображениями
- Фильтрация по:
- Категориям
- Диапазону цен
- Цвету
- Материалу
- Поиск по названию
- Добавление в корзину
#### Страница товара (`public/product.php`)
- Галерея изображений
- Описание и характеристики
- Цена и скидка
- Наличие на складе
- Кнопка добавления в корзину
- Рекомендуемые товары
#### Корзина (`public/checkout.php`)
- Список товаров в корзине
- Изменение количества
- Удаление товаров
- Расчет итоговой суммы
- Применение промокода
- Форма оформления заказа
---
## API Endpoints
### Аутентификация
#### POST `/api/auth.php`
Авторизация пользователя
**Запрос:**
```json
{
"email": "user@example.com",
"password": "password123"
}
```
**Ответ (успех):**
```json
{
"success": true,
"redirect": "catalog.php"
}
```
**Ответ (ошибка):**
```json
{
"success": false,
"message": "Неверный пароль"
}
```
---
### Корзина
#### POST `/api/cart.php?action=add`
Добавление товара в корзину
**Запрос:**
```json
{
"product_id": 1,
"quantity": 2
}
```
**Ответ:**
```json
{
"success": true,
"message": "Товар добавлен в корзину"
}
```
---
#### POST `/api/cart.php?action=update`
Обновление количества товара
**Запрос:**
```json
{
"product_id": 1,
"quantity": 3
}
```
---
#### POST `/api/cart.php?action=remove`
Удаление товара из корзины
**Запрос:**
```json
{
"product_id": 1
}
```
---
#### GET `/api/cart.php?action=get`
Получение содержимого корзины
**Ответ:**
```json
{
"success": true,
"items": [
{
"cart_id": 1,
"product_id": 5,
"quantity": 2,
"name": "Диван ROYALTY",
"price": 78999,
"image_url": "img2/6_6.png"
}
],
"total": 157998
}
```
---
#### GET `/api/cart.php?action=count`
Количество товаров в корзине
**Ответ:**
```json
{
"success": true,
"count": 3
}
```
---
### Товары
#### GET `/api/get_product.php?id=1`
Получение информации о товаре
**Ответ:**
```json
{
"success": true,
"product": {
"product_id": 1,
"name": "Светильник MINNIGHT",
"description": "Настольный светильник в современном стиле",
"price": 7999,
"old_price": 9999,
"image_url": "img2/1_2.png",
"color": "Черный",
"material": "Металл",
"stock_quantity": 15,
"is_available": true
}
}
```
---
### Заказы
#### POST `/api/process_order.php`
Оформление заказа
**Запрос:**
```json
{
"customer_name": "Иван Иванов",
"customer_email": "ivan@example.com",
"customer_phone": "+79001234567",
"delivery_address": "г. Москва, ул. Примерная, д. 1",
"delivery_method": "courier",
"payment_method": "card"
}
```
**Ответ:**
```json
{
"success": true,
"order_number": "AET-20251216-ABC123",
"message": "Заказ успешно оформлен"
}
```
---
## Административная панель
### Доступ
URL: `/admin/index.php` или `/public/catalog_admin.php`
Требуется авторизация с правами администратора (`is_admin = TRUE`)
### Функции
```mermaid
flowchart TD
A[Админ-панель] --> B[Dashboard]
A --> C[Категории]
A --> D[Товары]
A --> E[Заказы]
A --> F[Пользователи]
C --> C1[Список категорий]
C --> C2[Добавить категорию]
C --> C3[Редактировать]
C --> C4[Удалить]
D --> D1[Список товаров]
D --> D2[Добавить товар]
D --> D3[Редактировать]
D --> D4[Удалить]
D --> D5[Загрузка изображений]
E --> E1[Список заказов]
E --> E2[Детали заказа]
E --> E3[Изменить статус]
```
### Управление категориями
- Создание категорий и подкатегорий
- Редактирование названия и описания
- Установка порядка сортировки
- Активация/деактивация
### Управление товарами
- Добавление новых товаров
- Редактирование характеристик
- Загрузка изображений
- Установка цен и скидок
- Управление наличием
### Управление заказами
Статусы заказов:
| Статус | Описание |
|--------|----------|
| `pending` | Ожидает обработки |
| `processing` | В обработке |
| `shipped` | Отправлен |
| `delivered` | Доставлен |
| `cancelled` | Отменен |
---
## Функции и утилиты
### `includes/functions.php`
#### Проверка авторизации
```php
/**
* Проверка авторизации пользователя
*/
function isLoggedIn(): bool {
return isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true;
}
/**
* Проверка прав администратора
*/
function isAdmin(): bool {
return isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
}
```
#### Защита страниц
```php
/**
* Требовать авторизацию - редирект на login если не авторизован
*/
function requireAuth(string $redirectUrl = 'login.php'): void {
if (!isLoggedIn()) {
header('Location: ' . $redirectUrl . '?error=auth_required');
exit();
}
}
/**
* Требовать права администратора
*/
function requireAdmin(string $redirectUrl = 'login.php'): void {
if (!isAdmin()) {
header('Location: ' . $redirectUrl . '?error=admin_required');
exit();
}
}
```
#### Получение текущего пользователя
```php
/**
* Получить текущего пользователя
*/
function getCurrentUser(): ?array {
if (!isLoggedIn()) {
return null;
}
return [
'user_id' => $_SESSION['user_id'] ?? 0,
'email' => $_SESSION['user_email'] ?? '',
'full_name' => $_SESSION['full_name'] ?? '',
'is_admin' => isAdmin()
];
}
```
#### Форматирование
```php
/**
* Форматирование цены
*/
function formatPrice(float $price): string {
return number_format($price, 0, '', ' ') . ' ₽';
}
/**
* Безопасный вывод HTML
*/
function e(string $str): string {
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
}
```
#### Генерация идентификаторов
```php
/**
* Генерация номера заказа
*/
function generateOrderNumber(): string {
return 'AET-' . date('Ymd') . '-' . strtoupper(substr(uniqid(), -6));
}
/**
* Создание slug из строки
*/
function createSlug(string $str): string {
$slug = transliterate($str);
$slug = strtolower($slug);
$slug = preg_replace('/[^a-z0-9]+/', '-', $slug);
return trim($slug, '-');
}
```
#### Транслитерация
```php
/**
* Транслитерация кириллицы в латиницу
*/
function transliterate(string $str): string {
$converter = [
'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd',
'е' => 'e', 'ё' => 'e', 'ж' => 'zh', 'з' => 'z', 'и' => 'i',
// ... и т.д.
];
return strtr($str, $converter);
}
```
#### Flash-сообщения
```php
/**
* Установить flash-сообщение
*/
function setFlashMessage(string $type, string $message): void {
$_SESSION['flash_message'] = [
'type' => $type,
'message' => $message
];
}
/**
* Получить и удалить flash-сообщение
*/
function getFlashMessage(): ?array {
if (isset($_SESSION['flash_message'])) {
$message = $_SESSION['flash_message'];
unset($_SESSION['flash_message']);
return $message;
}
return null;
}
```
---
## Безопасность
### Защита от SQL-инъекций
Все запросы к базе данных используют подготовленные выражения (Prepared Statements):
```php
// ПРАВИЛЬНО - безопасно
$stmt = $db->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);
// НЕПРАВИЛЬНО - уязвимо для SQL-инъекций
$result = $db->query("SELECT * FROM users WHERE email = '$email'");
```
### Хеширование паролей
Пароли хешируются с использованием bcrypt:
```php
// Хеширование при регистрации
$password_hash = password_hash($password, PASSWORD_DEFAULT);
// Проверка при авторизации
if (password_verify($password, $user['password_hash'])) {
// Пароль верный
}
```
### Защита от XSS
Все пользовательские данные экранируются при выводе:
```php
// Безопасный вывод
echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
// Или используя функцию-хелпер
echo e($user_input);
```
### Защита сессий
```php
// Регенерация ID сессии после авторизации
session_regenerate_id(true);
// Проверка авторизации на каждой странице
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
header('Location: login.php');
exit();
}
```
### CSRF-защита
Рекомендуется добавить токены для форм:
```php
// Генерация токена
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
// В форме
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
// Проверка
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die('CSRF token mismatch');
}
```
### Проверка прав доступа
```php
// Проверка на каждой защищенной странице
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
header('Location: login.php?error=auth_required');
exit();
}
// Проверка прав администратора
if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) {
die('Доступ запрещен');
}
```
---
## Тестовые аккаунты
При подключении к удаленной DB доступны тестовые аккаунты:
### Администратор
| Поле | Значение |
|------|----------|
| Email | `admin@mail.ru` |
| Пароль | `admin123` |
| Имя | Администратор AETERNA |
| Права | Полный доступ к админ-панели |
---
## Разработка
### Создание новой миграции
1. Создайте файл `migrations/XXX_название.sql` (где XXX - следующий номер)
2. Напишите SQL-код
3. Запустите `php migrations/migrate.php`
Пример миграции:
```sql
-- 005_add_reviews.sql
-- Добавление таблицы отзывов
CREATE TABLE IF NOT EXISTS reviews (
review_id SERIAL PRIMARY KEY,
product_id INTEGER REFERENCES products(product_id) ON DELETE CASCADE,
user_id INTEGER REFERENCES users(user_id) ON DELETE SET NULL,
rating INTEGER CHECK (rating >= 1 AND rating <= 5),
comment TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_reviews_product ON reviews(product_id);
```
### Стиль кода
- Используйте PSR-12 для PHP
- Именование переменных: `snake_case`
- Именование функций: `camelCase` или `snake_case`
- Именование классов: `PascalCase`
- Комментируйте сложную логику
- Используйте типизацию где возможно
### Структура API endpoint
```php
<?php
session_start();
require_once __DIR__ . '/../config/database.php';
header('Content-Type: application/json; charset=utf-8');
// Проверка авторизации
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
echo json_encode(['success' => false, 'message' => 'Требуется авторизация']);
exit();
}
try {
$db = Database::getInstance()->getConnection();
// Ваша логика здесь
echo json_encode(['success' => true, 'data' => $result]);
} catch (PDOException $e) {
echo json_encode(['success' => false, 'message' => 'Ошибка базы данных']);
}
```
### Добавление новой страницы
1. Создайте файл в `public/`
2. Подключите header и footer
3. Добавьте проверку авторизации если нужно
4. Используйте единый стиль оформления
```php
<?php
session_start();
require_once __DIR__ . '/../config/database.php';
// Проверка авторизации (опционально)
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
header('Location: login.php');
exit();
}
?>
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>AETERNA - Название страницы</title>
<link rel="stylesheet/less" type="text/css" href="style_for_cite.less">
<script src="https://cdn.jsdelivr.net/npm/less"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
</head>
<body>
<?php include 'header_common.php'; ?>
<main class="container">
<!-- Ваш контент -->
</main>
<?php include 'footer.php'; ?>
</body>
</html>
```
---
## Диаграмма архитектуры
```mermaid
flowchart TB
subgraph client [Клиент]
Browser[Браузер]
end
subgraph server [Сервер]
subgraph public [Public Directory]
Index[index.php]
Catalog[catalog.php]
Product[product.php]
Checkout[checkout.php]
Login[login.php]
end
subgraph api [API Layer]
Auth[auth.php]
Cart[cart.php]
Order[process_order.php]
end
subgraph core [Core]
Config[database.php]
Functions[functions.php]
Includes[header/footer]
end
subgraph admin [Admin Panel]
AdminIndex[admin/index.php]
end
end
subgraph database [База данных]
PostgreSQL[(PostgreSQL)]
end
Browser <--> Index
Browser <--> Catalog
Browser <--> Product
Browser <--> Checkout
Browser <--> Login
Browser <--> Auth
Browser <--> Cart
Browser <--> Order
Browser <--> AdminIndex
Index --> Config
Catalog --> Config
Product --> Config
Checkout --> Config
Login --> Config
Auth --> Config
Cart --> Config
Order --> Config
AdminIndex --> Config
Config <--> PostgreSQL
```
---
## Поток оформления заказа
```mermaid
sequenceDiagram
participant U as Пользователь
participant B as Браузер
participant C as checkout.php
participant API as process_order.php
participant DB as PostgreSQL
U->>B: Открывает корзину
B->>C: GET /checkout.php
C->>DB: SELECT cart items
DB-->>C: Товары корзины
C-->>B: HTML страница корзины
U->>B: Заполняет форму заказа
U->>B: Нажимает "Оформить"
B->>API: POST /api/process_order.php
API->>DB: BEGIN TRANSACTION
API->>DB: INSERT INTO orders
DB-->>API: order_id
loop Для каждого товара
API->>DB: INSERT INTO order_items
API->>DB: UPDATE products (stock)
end
API->>DB: DELETE FROM cart
API->>DB: COMMIT
API-->>B: JSON success + order_number
B-->>U: Страница успеха
```