Вы когда-нибудь пытались сохранить данные из сайта в базу и получали кучу ошибок? Или боялись, что кто-то взломает ваш код через SQL-инъекции? Я покажу, как работать с базами данных в PHP через PDO — это просто, безопасно и даже весело. Представьте, что PDO — это универсальный переводчик между вашим PHP-кодом и любой базой данных. Он понимает MySQL, PostgreSQL, SQLite и других. И главное — он защищает вас от хакеров.

Что такое PDO и почему он лучше старых функций

PDO расшифровывается как PHP Data Objects. Это расширение PHP, которое даёт единый интерфейс для работы с разными базами данных. Раньше разработчики использовали функции вроде mysql_connect() или mysqli_*. У них были недостатки:

  • Они привязаны к конкретной базе данных. Если захотите перейти с MySQL на PostgreSQL, придётся переписывать весь код.
  • Они не защищают от SQL-инъекций, если не использовать подготовленные запросы вручную.
PDO решает обе проблемы. Вы пишете код один раз, и он работает с любой поддерживаемой базой. А подготовленные запросы в PDO — это встроенная защита.

Правило №1: Всегда используйте PDO для работы с базами данных. Это стандарт современного PHP. Даже в новых проектах на Laravel или Symfony внутри используется PDO.

Как подключиться к базе через PDO

Всё начинается с подключения. Для этого нужно создать объект PDO и передать ему три параметра: DSN (строка подключения), имя пользователя и пароль. DSN выглядит по-разному для разных баз. Вот пример для MySQL:

$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8';
$user = 'root';
$pass = '';

try {
    $pdo = new PDO($dsn, $user, $pass);
    echo 'Подключение успешно!';
} catch (PDOException $e) {
    die('Ошибка подключения: ' . $e->getMessage());
}

Обратите внимание на блок try-catch. Если что-то пойдёт не так (например, база данных недоступна), вы получите понятное сообщение об ошибке, а не белый экран. Для PostgreSQL DSN будет таким: pgsql:host=localhost;dbname=testdb. Для SQLite: sqlite:/path/to/database.db.

ПараметрОписаниеПример
hostСервер базы данныхlocalhost
dbnameИмя базы данныхtestdb
charsetКодировка (для MySQL)utf8

Безопасные запросы: подготовленные выражения

Главная фишка PDO — подготовленные выражения (prepared statements). Они отделяют SQL-код от данных. Вы сначала пишете запрос с плейсхолдерами (знаками вопроса или именованными метками), а потом передаёте значения отдельно. Это не даёт злоумышленникам внедрить вредоносный SQL-код.

Пример с именованными плейсхолдерами:

$sql = 'SELECT * FROM users WHERE email = :email';
$stmt = $pdo->prepare($sql);
$stmt->execute([':email' => 'user@example.com']);
$user = $stmt->fetch();

А вот пример с вопросительными знаками:

$sql = 'INSERT INTO posts (title, content) VALUES (?, ?)';
$stmt = $pdo->prepare($sql);
$stmt->execute(['Новый пост', 'Текст поста']);

В обоих случаях данные экранируются автоматически. Никаких кавычек вручную ставить не нужно.

Лайфхак: Если вы используете именованные плейсхолдеры, можно передавать ассоциативный массив без указания двоеточия в ключах. PDO сам добавит его, если нужно. Но лучше всегда писать с двоеточием для ясности.

Как получать данные: fetch и fetchAll

После выполнения запроса нужно извлечь результаты. PDO предлагает несколько методов. Самые популярные — fetch() для одной строки и fetchAll() для всех строк. Вы можете указать, в каком формате получать данные: ассоциативный массив, объект, нумерованный массив и так далее.

Пример получения всех пользователей в виде ассоциативных массивов:

$stmt = $pdo->query('SELECT * FROM users');
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($users as $user) {
    echo $user['name'] . ' - ' . $user['email'] . '
'; }

А вот как получить одну запись в виде объекта:

$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([1]);
$user = $stmt->fetch(PDO::FETCH_OBJ);
echo $user->name;
РежимОписание
PDO::FETCH_ASSOCАссоциативный массив (ключи — имена столбцов)
PDO::FETCH_OBJАнонимный объект
PDO::FETCH_NUMНумерованный массив
PDO::FETCH_BOTHИ ассоциативный, и нумерованный (по умолчанию)

Обработка ошибок: не дайте скрипту упасть

По умолчанию PDO не выводит ошибки — он просто возвращает false. Но это неудобно. Лучше включить режим исключений. Тогда при любой ошибке будет выбрасываться исключение PDOException, которое можно перехватить.

$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

try {
    $pdo->exec('INSERT INTO non_existent_table VALUES (1)');
} catch (PDOException $e) {
    echo 'Ошибка: ' . $e->getMessage();
}

Это особенно полезно при отладке. В продакшене вы можете логировать ошибки, а пользователю показывать красивое сообщение.

Важно: Никогда не выводите пользователю детали ошибок базы данных. Они могут раскрыть структуру вашей БД. Используйте общий текст вроде «Произошла ошибка, попробуйте позже».

Транзакции: когда нужно сохранить всё или ничего

Представьте, что вы переводите деньги с одного счёта на другой. Если после списания произойдёт ошибка, деньги пропадут. Транзакции решают эту проблему. Вы начинаете транзакцию, выполняете несколько запросов, и если всё прошло успешно — подтверждаете изменения (commit). Если что-то пошло не так — откатываете (rollback).

$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();
}

Транзакции работают только для баз данных, которые их поддерживают (MySQL с InnoDB, PostgreSQL). Для MyISAM они не имеют смысла.

Что в итоге

PDO — это мощный и безопасный инструмент для работы с базами данных в PHP. Он защищает от SQL-инъекций, упрощает смену базы данных и даёт удобные методы для работы с запросами. Главное — не забывайте про подготовленные выражения и обработку ошибок. Начните с малого: подключитесь к базе, выполните простой SELECT и INSERT. Потом добавьте транзакции и разные режимы выборки. Через пару дней вы будете чувствовать себя уверенно.

Студия WNDER