Вставка одной записи в MySQL через PHP: INSERT

Статья посвящена корректной и безопасной вставке одной строки в таблицу MySQL с помощью PHP. Рассматривается подход на базе PDO, который соответствует современным стандартам разработки.


Исходные данные: структура таблицы

Для демонстрации используется таблица users:

sql
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

Ключевые особенности схемы:

  • Поле id имеет автоинкремент — его не требуется указывать в INSERT.
  • Поля name и email объявлены как NOT NULL — отсутствие значений приведёт к ошибке.
  • Ограничение UNIQUE на поле email гарантирует отсутствие дубликатов; попытка вставить существующий адрес вызовет ошибку базы данных.

Безопасная вставка через PDO

Для взаимодействия с MySQL в современном PHP рекомендуется использовать расширение PDO. Основной принцип безопасности — применение подготовленных выражений (prepared statements) вместо прямой подстановки данных в SQL-запрос.

Пример реализации:

php
<?php
$dsn = 'mysql:host=localhost;dbname=test_db;charset=utf8mb4';
$user = 'db_user';
$pass = 'db_pass';
 
try {
    $pdo = new PDO($dsn, $user, $pass, [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ]);
 
    $sql = "INSERT INTO users (name, email) VALUES (:name, :email)";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([
        ':name'  => 'Иван Иванов',
        ':email' => 'ivan@example.com',
    ]);
 
    $lastId = $pdo->lastInsertId();
 
    echo 'Запись добавлена. ID новой строки: ' . $lastId;
} catch (PDOException $e) {
    echo 'Ошибка при вставке: запись не сохранена.';
    // В реальных проектах техническую ошибку следует записывать в лог, а не выводить пользователю
}
?>

Разбор ключевых этапов:

  1. Инициализация подключения. Переменная $dsn содержит параметры соединения, включая кодировку utf8mb4 для корректной работы с Unicode.
  2. Настройка режимов PDO. Установка PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION обеспечивает генерацию исключений при ошибках, что упрощает контроль состояния операции.
  3. Формирование SQL-запроса. В тексте запроса используются именованные плейсхолдеры (:name, :email) вместо прямых значений.
  4. Подготовка и выполнение. Метод prepare() подготавливает запрос, а execute() передаёт массив значений. На этом этапе происходит экранирование данных и защита от SQL-инъекций.
  5. Получение идентификатора. Метод lastInsertId() возвращает значение автоинкрементного поля id для только что вставленной строки.
  6. Обработка ошибок. Блок catch перехватывает исключения PDOException, позволяя корректно реагировать на сбои (например, при попытке вставить дубликат email).

Недопустимый подход: прямая подстановка данных

Ниже приведён пример, который не должен использоваться в реальных проектах:

php
// НЕДОПУСТИМО: уязвимость к SQL-инъекциям
$name = $_POST['name'];
$email = $_POST['email'];
$sql = "INSERT INTO users (name, email) VALUES ('$name', '$email')";
$pdo->exec($sql);

Недостатки такого подхода:

  • Отсутствие экранирования входных данных делает запрос уязвимым к SQL-инъекциям.
  • Некорректные значения (например, содержащие одинарные кавычки) могут привести к синтаксическим ошибкам.
  • Отсутствует структурированная обработка ошибок и контроль состояния операции.

Обработка типичных ошибок

При вставке данных могут возникнуть следующие ситуации:

  • Дубликат уникального поля. Если попытаться вставить уже существующий email, база данных вернёт ошибку. В коде это будет перехвачено блоком catch, где можно реализовать логику повторной попытки, уведомления пользователя или записи в журнал событий.
  • Нарушение NOT NULL. Пропуск обязательных полей также приведёт к ошибке на уровне СУБД.
  • Проблемы соединения. Ошибки аутентификации, недоступность сервера или неверные параметры подключения будут обработаны как исключения PDO.

Для производственных систем рекомендуется:

  • Вести логирование технических деталей ошибки (без вывода пользователю).
  • Предоставлять пользователю нейтральное сообщение о неудачной операции.
  • При необходимости — проверять данные на уровне приложения до отправки в базу (валидация формата email, длины строк и т. д.).

В реальных проектах логику работы с базой данных следует выносить в отдельные компоненты (классы, сервисы), а не размещать непосредственно в файлах отображения. Это обеспечивает:

  • Разделение ответственности между слоями приложения.
  • Упрощение тестирования и повторного использования кода.
  • Централизованную обработку ошибок и транзакций.

Добавить комментарий