Сохранение и обновление записей в MySQL через PHP

Раздел: Базы данных PHP -> Добавление данных

Запись данных в базу данных с помощью PDO

Наиболее современный и безопасный способ записи данных в базу данных из PHP - использование расширения PDO (PHP Data Objects) с подготовленными запросами. PDO поддерживает множество СУБД и защищает от SQL-инъекций.


$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare('INSERT INTO users (name, email) VALUES (:name, :email)');
$stmt->execute([':name' => 'Иван', ':email' => 'ivan@example.com']);
echo "Данные добавлены";

Php запись в базу данных (запись данных в базу данных php)

Пояснение: Создаётся подключение, включается режим исключений для обработки ошибок. Подготовленный запрос с именованными плейсхолдерами (:name, :email) затем выполняется с передачей ассоциативного массива. Это исключает возможность инъекций и автоматически экранирует значения.

Возникающие проблемы и их решение:

  • Ошибка подключения (неверный хост, логин, пароль). Решение: обернуть создание PDO в блок try-catch и ловить PDOException.
  • Дубликат уникального ключа. Решение: использовать INSERT IGNORE или ON DUPLICATE KEY UPDATE в запросе.
  • Несоответствие типов данных (например, строка вместо числа). Решение: явно указывать параметры с помощью bindValue и констант PDO::PARAM_*.

Как выполнить запись через объектно-ориентированный mysqli?


$mysqli = new mysqli('localhost', 'user', 'pass', 'test');
$stmt = $mysqli->prepare('INSERT INTO users (name, email) VALUES (?, ?)');
$stmt->bind_param('ss', $name, $email);
$name = 'Петр';
$email = 'petr@example.com';
$stmt->execute();

Цель: Использовать встроенное в PHP расширение MySQL, если PDO недоступен. Подготовленные запросы аналогичны PDO, но требуется ручное указание типов через строку 'ss'.

  • Ошибка при неверном порядке или количестве плейсхолдеров. Решение: строгая проверка соответствия bind_param.
  • Необходимость проверять $stmt->error после каждого вызова.

Как использовать процедурный стиль mysqli?


$conn = mysqli_connect('localhost', 'user', 'pass', 'test');
$stmt = mysqli_prepare($conn, 'INSERT INTO users (name, email) VALUES (?, ?)');
mysqli_stmt_bind_param($stmt, 'ss', $name, $email);
mysqli_stmt_execute($stmt);

Цель: Для проектов, где принят процедурный стиль кода. Требует тех же мер предосторожности, что и объектный mysqli.

  • Меньшая читаемость при большом количестве запросов.
  • Забывчивость передачи $conn в каждую функцию.

Как вставить данные, игнорируя ошибки дублирования?


$pdo->exec('INSERT IGNORE INTO users (id, name) VALUES (1, "test")');

Цель: Пропускать вставку, если такой ключ уже существует. Удобно для наполнения тестовых данных.

  • INSERT IGNORE подавляет не только дубликаты, но и другие ошибки (например, неверные типы). Решение: использовать ON DUPLICATE KEY UPDATE для более контролируемого поведения.

Как обеспечить атомарность записи с транзакциями?


$pdo->beginTransaction();
try {
    $pdo->exec('UPDATE accounts SET balance = balance - 100 WHERE id = 1');
    $pdo->exec('UPDATE accounts SET balance = balance + 100 WHERE id = 2');
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
    echo "Ошибка: " . $e->getMessage();
}

Цель: Гарантировать, что все изменения будут выполнены или полностью отменены.

  • Забывчивость вызова commit() или rollBack() приводит к блокировкам. Решение: всегда использовать try-catch.
  • Некоторые СУБД (MyISAM) не поддерживают транзакции. Решение: использовать InnoDB.

Расширенные примеры записи данных

Пакетная вставка нескольких записей в одной транзакции

Код:

Пример

$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
$pdo->beginTransaction();
$stmt = $pdo->prepare('INSERT INTO users (name, email) VALUES (:name, :email)');
$users = [
    ['name' => 'Anna', 'email' => 'anna@example.com'],
    ['name' => 'Bob', 'email' => 'bob@example.com'],
    ['name' => 'Charlie', 'email' => 'charlie@example.com']
];
foreach ($users as $user) {
    $stmt->execute($user);
}
$pdo->commit();
echo "Добавлено " . count($users) . " записей.";

Результат:

Добавлено 3 записей.

Транзакция гарантирует, что все три записи будут вставлены атомарно. При ошибке в одной из них произойдёт откат.

Вставка с возвратом последнего ID

Пример

$pdo = new PDO('...');
$stmt = $pdo->prepare('INSERT INTO posts (title, body) VALUES (:title, :body)');
$stmt->execute([':title' => 'Новый пост', ':body' => 'Содержимое']);
$postId = $pdo->lastInsertId();
echo "Создан пост с ID: $postId";
Создан пост с ID: 42

Примечание: Метод lastInsertId() возвращает ID, сгенерированный последним INSERT в текущем соединении. Работает только если таблица имеет поле с AUTO_INCREMENT.

Запись с обработкой дубликатов (ON DUPLICATE KEY UPDATE)

Пример

$stmt = $pdo->prepare('
    INSERT INTO page_views (page_slug, views) VALUES (:slug, 1)
    ON DUPLICATE KEY UPDATE views = views + 1
');
$stmt->execute([':slug' => 'home']);
echo "Счётчик обновлён.";
Счётчик обновлён.

Этот запрос либо вставляет новую строку, либо увеличивает существующий счётчик. Поле page_slug должно быть уникальным (PRIMARY KEY или UNIQUE).

Использование именованных плейсхолдеров с явным указанием типов

Пример

$stmt = $pdo->prepare('INSERT INTO products (name, price, active) VALUES (:name, :price, :active)');
$stmt->bindValue(':name', 'Книга', PDO::PARAM_STR);
$stmt->bindValue(':price', 15.99, PDO::PARAM_STR);
$stmt->bindValue(':active', 1, PDO::PARAM_INT);
$stmt->execute();

Привязка через bindValue позволяет указать тип параметра, что может быть критично для некоторых СУБД. Позиционные плейсхолдеры (?) менее читаемы, но тоже допустимы.

Вставка значений NULL

Пример

$stmt = $pdo->prepare('INSERT INTO users (email, deleted_at) VALUES (?, ?)');
$stmt->execute(['user@example.com', null]);
echo "Пользователь с NULL датой удаления.";

При передаче null в execute PDO автоматически преобразует его в SQL NULL.

Запись данных в базу данных PHP - comments

En
Php запись в базу данных (php)