Основы баз данных: Проектирование БД и работа с MySQL
Студент познакомится с реляционными базами данных, спроектирует структуру таблиц для интернет-магазина и напишет базовые SQL-запросы.
Реляционные базы данных и нормализация
Любой интернет-магазин должен где-то хранить данные пользователей, товаров и заказов. Для этого используются Системы Управления Базами Данных (СУБД). Мы будем использовать MySQL — самую популярную реляционную СУБД в экосистеме PHP. "Реляционная" означает, что данные хранятся в таблицах (состоящих из строк и столбцов), которые связаны между собой отношениями (relations). Проектирование структуры БД — критически важный этап. Ошибка здесь приведет к огромным проблемам при масштабировании.
В архивных материалах описана миграция для таблицы products. Каждая таблица должна иметь Первичный ключ (Primary Key) — обычно это колонка id, уникально идентифицирующая запись. Для связи таблиц используются Внешние ключи (Foreign Keys). Например, в таблице товаров есть category_id, который ссылается на id в таблице категорий. Это связь "Один ко многим" (одна категория содержит много товаров). Нормализация баз данных — это процесс организации таблиц для минимизации избыточности (дублирования) данных. Вместо того чтобы в каждом товаре писать название категории текстом, мы храним только числовой ID категории.
| Имя колонки | Тип данных MySQL | Описание |
|---|---|---|
| id | BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY | Уникальный идентификатор |
| category_id | BIGINT UNSIGNED FOREIGN KEY | Связь с таблицей категорий |
| name | VARCHAR(255) | Название товара |
| price | DECIMAL(8, 2) | Цена (8 цифр всего, 2 после запятой) |
Подключение к MySQL через PDO и защита от SQL-инъекций
Для работы с базами данных в PHP используется расширение PDO (PHP Data Objects). PDO предоставляет единый интерфейс для доступа к различным базам данных и поддерживает подготовленные выражения (Prepared Statements). Подготовленные выражения — это абсолютный стандарт безопасности веб-разработки. Они полностью защищают приложение от SQL-инъекций — самого распространенного типа атак, при котором злоумышленник пытается внедрить вредоносный SQL-код через поля ввода.
В архивном упражнении 2.1 показан правильный подход. Мы сначала создаем объект подключения $pdo, передавая DSN (Data Source Name), логин и пароль. Затем мы не вставляем переменные напрямую в SQL-строку (НИКОГДА не делайте "SELECT * FROM products WHERE price > $price"). Вместо этого мы пишем запрос с плейсхолдером :price, подготавливаем его методом prepare(), и только потом выполняем execute(), передавая массив со значениями. База данных сама безопасно подставит значения. Результат мы получаем методом fetchAll(). Мы настраиваем PDO на режим FETCH_ASSOC, чтобы получить данные в виде удобного ассоциативного массива.
<?php
// Архивные материалы: Подключение и выборка через PDO
$dsn = 'mysql:host=localhost;dbname=shop;charset=utf8mb4';
$user = 'root';
$password = 'secret';
try {
$pdo = new PDO($dsn, $user, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);
// Использование подготовленных выражений для безопасности
$stmt = $pdo->prepare('SELECT * FROM products WHERE price > :price');
$stmt->execute(['price' => 100]);
$products = $stmt->fetchAll();
foreach ($products as $product) {
echo $product['name'] . " - $" . $product['price'] . "\n";
}
} catch (PDOException $e) {
die("Ошибка подключения: " . $e->getMessage());
}
Почему необходимо использовать подготовленные выражения (Prepared Statements) в PDO?
Какой тип данных MySQL лучше всего использовать для хранения точных денежных сумм (цены товара), чтобы избежать ошибок округления?
Задание
Практика: Вставка данных (INSERT)
- Напишите SQL-запрос INSERT для таблицы orders (user_id, total_price).
- Используйте именованные плейсхолдеры :user_id и :total_price.
- Используйте метод $pdo->prepare().
- Вызовите execute(), передав массив со значениями (например, user_id => 1, total_price => 250.00).