Если вы пишете на PHP, рано или поздно вам придётся работать с базой данных. И тут начинается: mysql_connect, mysqli, а может, PDO? Сегодня разберём, почему PDO — это не просто модный акроним, а ваш надёжный друг и защитник. Статья поможет новичкам освоить основы, а опытным — освежить знания.

Digital-студия WNDER

Что такое PDO и зачем он нужен?

PDO расшифровывается как PHP Data Objects. Это расширение PHP, которое предоставляет единый интерфейс для работы с разными базами данных: MySQL, PostgreSQL, SQLite, Oracle и другими. Вместо того чтобы учить кучу разных функций для каждой СУБД, вы используете один набор методов. Красота!

Главная фишка PDO — подготовленные выражения (prepared statements). Они защищают от SQL-инъекций, делают код чище и безопаснее. Если вы до сих пор собираете запросы конкатенацией строк — бросайте это дело, переходите на PDO.

Подключение к базе данных

Начнём с подключения. Допустим, у нас MySQL. Создаём объект PDO:


<?php
$host = 'localhost';
$db   = 'test_db';
$user = 'root';
$pass = '';
$charset = 'utf8mb4';

$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
];

try {
    $pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
    throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
?>

Здесь мы задаём DSN (Data Source Name) — строку с типом БД, хостом, именем базы и кодировкой. Опции: включаем исключения при ошибках, устанавливаем режим выборки по умолчанию (ассоциативный массив) и отключаем эмуляцию подготовленных запросов (чтобы они были настоящими).

Правило: Всегда отключайте эмуляцию подготовленных запросов (PDO::ATTR_EMULATE_PREPARES => false). Это гарантирует, что запросы действительно подготавливаются на стороне сервера, а не эмулируются PHP, что повышает безопасность.

Основные операции: SELECT, INSERT, UPDATE, DELETE

Теперь научимся выполнять запросы. Для SELECT используем метод query, если нет параметров, или prepare + execute, если есть условия.

Пример выборки с условием:


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

Для вставки, обновления и удаления тоже используем подготовленные выражения:


// Вставка
$stmt = $pdo->prepare('INSERT INTO users (name, email) VALUES (:name, :email)');
$stmt->execute(['name' => 'Иван', 'email' => 'ivan@example.com']);

// Обновление
$stmt = $pdo->prepare('UPDATE users SET name = :name WHERE id = :id');
$stmt->execute(['name' => 'Пётр', 'id' => 1]);

// Удаление
$stmt = $pdo->prepare('DELETE FROM users WHERE id = :id');
$stmt->execute(['id' => 1]);

Обратите внимание на именованные плейсхолдеры (например, :email). Они делают код читаемым. Можно использовать и вопросительные знаки, но тогда нужно следить за порядком параметров.

Обработка ошибок и отладка

PDO может сообщать об ошибках тремя способами: тихо (по умолчанию), предупреждениями или исключениями. Мы уже установили режим исключений — это самый удобный вариант. При ошибке скрипт прервётся, и вы увидите, что не так.

Но не забывайте оборачивать потенциально опасные участки в try-catch, чтобы gracefully обработать ситуацию:


try {
    $pdo->beginTransaction();
    // несколько запросов
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
    echo 'Ошибка: ' . $e->getMessage();
}

Транзакции помогают поддерживать целостность данных. Если что-то пошло не так, откатываем изменения.

Полезные методы и приёмы

Вот несколько методов, которые часто используются:

Метод Описание
fetch() Возвращает одну строку результата
fetchAll() Возвращает все строки в виде массива
rowCount() Количество затронутых строк
lastInsertId() ID последней вставленной записи
quote() Экранирует строку для использования в запросе (но лучше использовать подготовленные выражения)

Также можно настраивать режим выборки для каждого запроса отдельно:


$stmt = $pdo->query('SELECT * FROM users');
$users = $stmt->fetchAll(PDO::FETCH_OBJ); // вернёт объекты
Лайфхак: Используйте метод fetchAll(PDO::FETCH_KEY_PAIR), чтобы получить ассоциативный массив, где ключ — первый столбец, значение — второй. Удобно для выпадающих списков.

Заключение

PDO — это мощный и гибкий инструмент для работы с базами данных в PHP. Он обеспечивает безопасность, переносимость и удобство. Начните с простых запросов, постепенно осваивайте транзакции и продвинутые настройки. И помните: безопасность превыше всего.

В итоге вы получаете чистый код, защищённый от инъекций, и лёгкость при смене СУБД. Попробуйте переписать свои старые скрипты на PDO — результат вас приятно удивит.

Студия WNDER