Создание базы данных и веб-приложения для предоставления товаров и услуг
Пошаговое руководство по разработке масштабируемой и безопасной платформы
Ключевые выводы:
- Комплексное проектирование базы данных: Создание структурированных таблиц для эффективного хранения и управления данными.
- Безопасность и масштабируемость: Внедрение современных методов защиты данных и обеспечения производительности системы.
- Интеграция Frontend и Backend: Использование современных технологий для обеспечения плавного взаимодействия между клиентской и серверной частями приложения.
1. Проектирование базы данных
1.1. Определение основных сущностей
Для реализации веб-сайта, предоставляющего товары и услуги с категориями и подкатегориями, необходимо определить следующие основные сущности:
- Пользователи (users): Хранение информации о пользователях, включая аутентификационные данные.
- Категории (categories) и Подкатегории (subcategories): Организация товаров и услуг по тематическим разделам.
- Товары (products): Информация о продуктах, включая описание, цену и фотографии.
- Услуги (services): Описание предоставляемых услуг с примерами проектов.
- Проекты (projects): Примеры выполненных проектов для каждой услуги, включая фотографии и описания.
- Заказы (orders): Информация о заказах пользователей на товары и услуги.
- Комментарии (comments): Отзывы и комментарии пользователей к проектам.
1.2. Схема базы данных
Ниже представлена схема базы данных с описанием основных таблиц и их связей:
| Таблица | Поля | Описание |
|---|---|---|
| users |
id SERIAL PRIMARY KEY, username VARCHAR(50) UNIQUE NOT NULL, email VARCHAR(100) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, role VARCHAR(20) DEFAULT 'user', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
Хранение данных пользователей. |
| categories |
id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, parent_id INT REFERENCES categories(id) ON DELETE SET NULL |
Основные категории товаров и услуг, с иерархией подкатегорий. |
| products |
id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, description TEXT, price DECIMAL(10,2) NOT NULL, image_url VARCHAR(255), category_id INT REFERENCES categories(id) ON DELETE SET NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
Информация о товарах, включая описание, цену и изображение. |
| services |
id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, description TEXT, image_url VARCHAR(255), category_id INT REFERENCES categories(id) ON DELETE SET NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
Описание услуг с привязкой к категориям. |
| projects |
id SERIAL PRIMARY KEY, service_id INT REFERENCES services(id) ON DELETE CASCADE, name VARCHAR(255) NOT NULL, description TEXT, image_url VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
Примеры проектов для услуг с описаниями и изображениями. |
| orders |
id SERIAL PRIMARY KEY, user_id INT REFERENCES users(id) ON DELETE CASCADE, total_amount DECIMAL(10,2) NOT NULL, status VARCHAR(20) DEFAULT 'pending', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
Заказы пользователей на товары и услуги. |
| order_items |
id SERIAL PRIMARY KEY, order_id INT REFERENCES orders(id) ON DELETE CASCADE, product_id INT REFERENCES products(id) ON DELETE SET NULL, service_id INT REFERENCES services(id) ON DELETE SET NULL, quantity INT NOT NULL, price DECIMAL(10,2) NOT NULL |
Элементы заказа, связывающие заказы с товарами или услугами. |
| comments |
id SERIAL PRIMARY KEY, project_id INT REFERENCES projects(id) ON DELETE CASCADE, user_id INT REFERENCES users(id) ON DELETE CASCADE, content TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
Комментарии пользователей к проектам. |
1.3. Скрипты создания таблиц
Ниже приведены SQL-скрипты для создания всех необходимых таблиц:
-- Таблица пользователей
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
role VARCHAR(20) DEFAULT 'user',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Таблица категорий
CREATE TABLE categories (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
parent_id INT REFERENCES categories(id) ON DELETE SET NULL
);
-- Таблица товаров
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
price DECIMAL(10,2) NOT NULL,
image_url VARCHAR(255),
category_id INT REFERENCES categories(id) ON DELETE SET NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Таблица услуг
CREATE TABLE services (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
image_url VARCHAR(255),
category_id INT REFERENCES categories(id) ON DELETE SET NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Таблица проектов
CREATE TABLE projects (
id SERIAL PRIMARY KEY,
service_id INT REFERENCES services(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
description TEXT,
image_url VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Таблица заказов
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(id) ON DELETE CASCADE,
total_amount DECIMAL(10,2) NOT NULL,
status VARCHAR(20) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Таблица элементов заказа
CREATE TABLE order_items (
id SERIAL PRIMARY KEY,
order_id INT REFERENCES orders(id) ON DELETE CASCADE,
product_id INT REFERENCES products(id) ON DELETE SET NULL,
service_id INT REFERENCES services(id) ON DELETE SET NULL,
quantity INT NOT NULL,
price DECIMAL(10,2) NOT NULL
);
-- Таблица комментариев
CREATE TABLE comments (
id SERIAL PRIMARY KEY,
project_id INT REFERENCES projects(id) ON DELETE CASCADE,
user_id INT REFERENCES users(id) ON DELETE CASCADE,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
2. Настройка PostgreSQL
2.1. Установка PostgreSQL
Установите PostgreSQL на ваш сервер или локальную машину. Руководство по установке доступно на официальном сайте PostgreSQL Download.
2.2. Создание базы данных
После установки запустите PostgreSQL и создайте новую базу данных:
CREATE DATABASE ecommerce;
2.3. Настройка таблиц
Выполните ранее представленные SQL-скрипты для создания всех необходимых таблиц в базе данных ecommerce.
3. Настройка Backend на Node.js с использованием ES6 импортов
3.1. Инициализация проекта
Создайте новый проект и инициализируйте его с помощью npm:
mkdir backend
cd backend
npm init -y
3.2. Установка зависимостей
Установите необходимые библиотеки:
npm install express pg bcrypt jsonwebtoken cors dotenv
npm install --save-dev nodemon
3.3. Структура проекта
Создайте следующую структуру каталогов для организации кода:
backend/
├── config/
│ └── db.js
├── controllers/
│ ├── authController.js
│ ├── productController.js
│ ├── serviceController.js
│ └── orderController.js
├── middleware/
│ └── authMiddleware.js
├── models/
│ ├── User.js
│ ├── Product.js
│ ├── Service.js
│ └── Order.js
├── routes/
│ ├── authRoutes.js
│ ├── productRoutes.js
│ ├── serviceRoutes.js
│ └── orderRoutes.js
├── .env
├── app.js
└── server.js
3.4. Конфигурация подключения к базе данных
Создайте файл config/db.js и настройте подключение к PostgreSQL:
import pg from 'pg';
const { Pool } = pg;
const pool = new Pool({
user: process.env.DB_USER,
host: process.env.DB_HOST,
database: process.env.DB_NAME,
password: process.env.DB_PASSWORD,
port: process.env.DB_PORT,
});
export default pool;
3.5. Настройка переменных окружения
Создайте файл .env в корне проекта и добавьте следующие переменные:
PORT=5000
DB_USER=your_db_user
DB_HOST=localhost
DB_NAME=ecommerce
DB_PASSWORD=your_db_password
DB_PORT=5432
JWT_SECRET=your_jwt_secret
3.6. Создание серверного приложения
Создайте файл app.js и настройте Express-приложение:
import express from 'express';
import cors from 'cors';
import dotenv from 'dotenv';
import authRoutes from './routes/authRoutes.js';
import productRoutes from './routes/productRoutes.js';
import serviceRoutes from './routes/serviceRoutes.js';
import orderRoutes from './routes/orderRoutes.js';
dotenv.config();
const app = express();
// Middleware
app.use(cors());
app.use(express.json());
// Routes
app.use('/api/auth', authRoutes);
app.use('/api/products', productRoutes);
app.use('/api/services', serviceRoutes);
app.use('/api/orders', orderRoutes);
export default app;
Создайте файл server.js для запуска сервера:
import app from './app.js';
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`Сервер запущен на порту ${PORT}`);
});
3.7. Реализация аутентификации и авторизации
Создайте файл middleware/authMiddleware.js для проверки JWT-токенов:
import jwt from 'jsonwebtoken';
export const authMiddleware = (req, res, next) => {
const token = req.headers['authorization'];
if (!token) {
return res.status(403).send('Токен не предоставлен.');
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (err) {
return res.status(401).send('Недействительный токен.');
}
};
3.8. Создание маршрутов и контроллеров
Пример реализации маршрутов и контроллеров для аутентификации:
routes/authRoutes.js
import express from 'express';
import { register, login } from '../controllers/authController.js';
const router = express.Router();
router.post('/register', register);
router.post('/login', login);
export default router;
controllers/authController.js
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import pool from '../config/db.js';
export const register = async (req, res) => {
const { username, email, password } = req.body;
const hashedPassword = await bcrypt.hash(password, 10);
try {
await pool.query(
'INSERT INTO users (username, email, password) VALUES ($1, $2, $3)',
[username, email, hashedPassword]
);
res.status(201).send('Пользователь зарегистрирован.');
} catch (err) {
res.status(500).send(err.message);
}
};
export const login = async (req, res) => {
const { email, password } = req.body;
try {
const userResult = await pool.query('SELECT * FROM users WHERE email = $1', [email]);
const user = userResult.rows[0];
if (!user || !(await bcrypt.compare(password, user.password))) {
return res.status(401).send('Неправильные учетные данные.');
}
const token = jwt.sign({ id: user.id, email: user.email }, process.env.JWT_SECRET, { expiresIn: '1h' });
res.json({ token });
} catch (err) {
res.status(500).send(err.message);
}
};
4. Настройка Frontend на Vue 3
4.1. Инициализация проекта Vue 3
Перейдите в корневую директорию проекта и инициализируйте новый проект Vue 3:
mkdir frontend
cd frontend
npm init vue@latest
# Следуйте инструкциям для настройки проекта
4.2. Установка зависимостей
Установите необходимые пакеты:
npm install vue@next vue-router@4 axios
4.3. Структура проекта
Организуйте структуру проекта следующим образом:
frontend/
├── src/
│ ├── assets/
│ ├── components/
│ │ ├── common/
│ │ ├── products/
│ │ ├── services/
│ │ └── orders/
│ ├── views/
│ │ ├── Home.vue
│ │ ├── Login.vue
│ │ ├── Register.vue
│ │ ├── Products.vue
│ │ ├── Services.vue
│ │ └── Order.vue
│ ├── router/
│ │ └── index.js
│ ├── App.vue
│ └── main.js
├── .env
└── package.json
4.4. Настройка маршрутизации с помощью Vue Router
Создайте файл src/router/index.js и настройте маршруты:
import { createRouter, createWebHistory } from 'vue-router';
import Home from '../views/Home.vue';
import Products from '../views/Products.vue';
import Services from '../views/Services.vue';
import Login from '../views/Login.vue';
import Register from '../views/Register.vue';
import Order from '../views/Order.vue';
const routes = [
{ path: '/', name: 'Home', component: Home },
{ path: '/products', name: 'Products', component: Products },
{ path: '/services', name: 'Services', component: Services },
{ path: '/login', name: 'Login', component: Login },
{ path: '/register', name: 'Register', component: Register },
{ path: '/order', name: 'Order', component: Order, meta: { requiresAuth: true } },
];
const router = createRouter({
history: createWebHistory(),
routes,
});
// Глобальная защита маршрутов
router.beforeEach((to, from, next) => {
const isAuthenticated = localStorage.getItem('token');
if (to.meta.requiresAuth && !isAuthenticated) {
next('/login');
} else {
next();
}
});
export default router;
4.5. Основной файл приложения
Настройте файл src/main.js для инициализации Vue-приложения:
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
createApp(App).use(router).mount('#app');
4.6. Создание компонентов и страниц
Создайте необходимые компоненты для отображения товаров, услуг, заказов и взаимодействия с пользователем. Пример компонента для отображения списка продуктов:
components/products/ProductList.vue
<template>
<div class="product-list">
<div v-for="product in products" :key="product.id" class="product-item">
<img :src="product.image_url" :alt="product.name" />
<h3>{{ product.name }}</h3>
<p>{{ product.description }}</p>
<p>Цена: {{ product.price }} руб.</p>
<button @click="addToOrder(product)">Заказать</button>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
products: [],
};
},
methods: {
async fetchProducts() {
try {
const response = await axios.get('http://localhost:5000/api/products');
this.products = response.data;
} catch (error) {
console.error(error);
}
},
addToOrder(product) {
// Логика добавления продукта в заказ
},
},
created() {
this.fetchProducts();
},
};
</script>
<style scoped>
/* Стили для компонента */
.product-item {
border: 1px solid #ccc;
padding: 16px;
margin: 16px;
}
</style>
5. Связь Frontend и Backend
5.1. Использование Axios для HTTP-запросов
Установите Axios для взаимодействия с API:
npm install axios
Создайте файл src/services/api.js для настройки Axios:
import axios from 'axios';
const api = axios.create({
baseURL: 'http://localhost:5000/api',
});
export default api;
5.2. Аутентификация пользователей
Реализуйте методы регистрации и входа, храня токен в localStorage:
components/auth/Register.vue
<template>
<form @submit.prevent="register">
<input v-model="username" placeholder="Имя пользователя" required />
<input v-model="email" type="email" placeholder="Email" required />
<input v-model="password" type="password" placeholder="Пароль" required />
<button type="submit">Регистрация</button>
</form>
</template>
<script>
import api from '@/services/api';
export default {
data() {
return {
username: '',
email: '',
password: '',
};
},
methods: {
async register() {
try {
await api.post('/auth/register', {
username: this.username,
email: this.email,
password: this.password,
});
this.$router.push('/login');
} catch (error) {
console.error(error);
}
},
},
};
</script>
5.3. Создание заказов
Реализуйте функционал для создания заказов пользователями:
components/orders/OrderForm.vue
<template>
<form @submit.prevent="createOrder">
<div v-for="item in orderItems" :key="item.id">
<input v-model="item.quantity" type="number" min="1" />
<button @click="removeItem(item)">Удалить</button>
</div>
<button @click="addItem">Добавить товар/услугу</button>
<button type="submit">Оформить заказ</button>
</form>
</template>
<script>
import api from '@/services/api';
export default {
data() {
return {
orderItems: [],
};
},
methods: {
addItem() {
this.orderItems.push({ product_id: null, service_id: null, quantity: 1, price: 0 });
},
removeItem(item) {
this.orderItems = this.orderItems.filter(i => i !== item);
},
async createOrder() {
try {
const token = localStorage.getItem('token');
const response = await api.post('/orders', { items: this.orderItems }, {
headers: { Authorization: token },
});
console.log('Заказ оформлен:', response.data);
} catch (error) {
console.error(error);
}
},
},
};
</script>
6. Безопасность и масштабируемость
6.1. Обеспечение безопасности
- Использование HTTPS: Обеспечьте защиту данных путем использования SSL-сертификатов для шифрования трафика.
- Хэширование паролей: Пароли пользователей хэшируются с использованием
bcryptперед сохранением в базе данных. - Валидация данных: Все входные данные проверяются на стороне сервера для предотвращения SQL-инъекций и других атак.
- Аутентификация через JWT: Используйте JSON Web Tokens для безопасной аутентификации пользователей.
- Настройка CORS: Ограничьте доступ к API только разрешенными источниками.
6.2. Масштабируемость системы
- Кэширование: Используйте Redis или аналогичные решения для кэширования часто запрашиваемых данных, таких как список товаров.
- Балансировка нагрузки: Внедрите балансировщики нагрузки (например, Nginx) для распределения запросов между несколькими серверами.
- Масштабируемая архитектура: Используйте микросервисную архитектуру для разделения различных компонентов приложения.
- Контейнеризация: Применяйте Docker для упрощения развертывания и управления зависимостями.
- Мониторинг и логирование: Внедрите системы мониторинга (например, Prometheus) и логирования (например, ELK stack) для отслеживания состояния приложения и быстрого выявления проблем.
7. Тестирование и развертывание
7.1. Тестирование API
Используйте инструменты, такие как Postman, для тестирования всех конечных точек API и обеспечения их корректной работы.
7.2. Развертывание приложения
-
Backend: Разверните сервер Node.js на платформе, такой как Heroku, AWS или DigitalOcean.
-
Frontend: Скомпилируйте приложение Vue 3 и разверните его на CDN или веб-сервере.
-
База данных: Разместите PostgreSQL на управляемом сервисе, например, AWS RDS.
-
Контейнеризация: Используйте Docker для упаковки всех компонентов приложения и управления ими.
7.3. Интеграция CI/CD
Настройте процессы непрерывной интеграции и непрерывного развертывания (CI/CD) с использованием GitHub Actions, GitLab CI или других сервисов для автоматизации тестирования и деплоя.
Заключение
Следуя данному пошаговому руководству, вы сможете создать надежное, безопасное и масштабируемое веб-приложение для предоставления товаров и услуг. Внимательно следуйте рекомендациям по проектированию базы данных, настройке серверной и клиентской части, а также обеспечению безопасности и масштабируемости системы.
Ссылки на источники:
Last updated January 20, 2025