Вы когда-нибудь пытались сохранить данные из сайта в базу и получали кучу ошибок? Или боялись, что кто-то взломает ваш код через SQL-инъекции? Я покажу, как работать с базами данных в PHP через PDO — это просто, безопасно и даже весело. Представьте, что PDO — это универсальный переводчик между вашим PHP-кодом и любой базой данных. Он понимает MySQL, PostgreSQL, SQLite и других. И главное — он защищает вас от хакеров.
Что такое PDO и почему он лучше старых функций
PDO расшифровывается как PHP Data Objects. Это расширение PHP, которое даёт единый интерфейс для работы с разными базами данных. Раньше разработчики использовали функции вроде mysql_connect() или mysqli_*. У них были недостатки:
- Они привязаны к конкретной базе данных. Если захотите перейти с MySQL на PostgreSQL, придётся переписывать весь код.
- Они не защищают от SQL-инъекций, если не использовать подготовленные запросы вручную.
Как подключиться к базе через 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(['Новый пост', 'Текст поста']);В обоих случаях данные экранируются автоматически. Никаких кавычек вручную ставить не нужно.
Как получать данные: 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. Потом добавьте транзакции и разные режимы выборки. Через пару дней вы будете чувствовать себя уверенно.


