Подключение к MySQL через PDO: что знать до начала
За 20 минут вы получите рабочее подключение к MySQL через PDO, настроенное так, чтобы падало с понятной ошибкой, а не молчало. Разбираем DSN, режим ошибок и кодировку до того, как что-то сломается.

К концу этой инструкции у вас будет PHP-скрипт, который подключается к базе MySQL, выполняет запрос и выводит результат. Настроено так, чтобы при ошибке вы видели внятное исключение, а не белый экран. Времени уйдёт минут двадцать, если PHP и MySQL уже установлены.
Речь про PDO — встроенный в PHP слой доступа к базам. Он идёт в комплекте с PHP и работает не только с MySQL, но здесь мы берём именно MySQL 8.x и PHP 8.x. На старых версиях PHP 7.x код тоже запустится, различия отмечу отдельно.
Что нужно иметь до начала
Проверьте это до первой строки кода — иначе застрянете на середине.
- PHP 8.0 или новее. Проверка: в терминале
php -v. Версия ниже 8.0 тоже подойдёт, но пример с исключениями по умолчанию рассчитан на 8.x. - Расширение pdo_mysql включено. Проверка:
php -m | grep pdo_mysql(Linux/macOS) илиphp -mв Windows и поиск строкиpdo_mysqlглазами. Если строки нет — расширение не подключено, к базе вы не достучитесь. - Работающий сервер MySQL и доступы к нему: хост, порт, имя базы, логин и пароль. Обычно хост —
127.0.0.1, порт —3306. - Существующая база данных. PDO не создаёт базу за вас. Если базы нет, создайте её заранее:
CREATE DATABASE shop CHARACTER SET utf8mb4;
Если pdo_mysql в списке модулей нет — на Debian/Ubuntu ставится пакетом php-mysql, на Windows раскомментируйте строку extension=pdo_mysql в файле php.ini и перезапустите веб-сервер. Точное имя пакета зависит от того, как у вас установлен PHP — сверьтесь с инструкцией вашего дистрибутива.
Шаг 1. Собираем строку подключения (DSN)
PDO принимает данные для подключения в виде строки — DSN (Data Source Name). Для MySQL она выглядит так:
mysql:host=127.0.0.1;port=3306;dbname=shop;charset=utf8mb4Разберём по частям, что куда вписывать:
| Часть DSN | Что означает | Пример значения |
|---|---|---|
mysql: | драйвер, всегда так для MySQL | mysql: |
host | адрес сервера базы | 127.0.0.1 |
port | порт MySQL, можно опустить если 3306 | 3306 |
dbname | имя вашей базы | shop |
charset | кодировка соединения | utf8mb4 |
Про charset=utf8mb4 — не пропускайте его. Без явного указания кодировки соединение может работать в latin1, и русский текст или эмодзи превратятся в мусор при записи. utf8mb4 — это полноценный UTF-8 в MySQL, в отличие от урезанного utf8, который не хранит эмодзи.
Шаг 2. Создаём подключение
Вот полный рабочий скрипт. Скопируйте его в файл db.php, подставьте свои доступы и запустите php db.php.
<?php
// PHP 8.x, MySQL 8.x
$host = '127.0.0.1';
$port = 3306;
$dbName = 'shop';
$user = 'root';
$password = 'YOUR_DB_PASSWORD';
$dsn = "mysql:host=$host;port=$port;dbname=$dbName;charset=utf8mb4";
// Опции подключения задают поведение PDO
$options = [
// Бросать исключение при любой ошибке SQL
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, $password, $options);
echo "Подключение установлено\n";
} catch (PDOException $e) {
// Не показывайте текст ошибки конечному пользователю в проде
echo 'Ошибка подключения: ' . $e->getMessage() . "\n";
exit(1);
}Если вы увидели строку «Подключение установлено» — соединение работает. Три опции в массиве важнее самого подключения, поэтому остановлюсь на них.
PDO по умолчанию молчит об ошибках SQL. Строка PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION превращает молчаливые сбои в исключения — именно с неё стоит начинать любое подключение. В PHP 8.0 этот режим стал поведением по умолчанию, но в 7.x его нужно указывать руками.Почему EMULATE_PREPARES отключаем
По умолчанию PDO для MySQL «эмулирует» подготовленные запросы — подставляет значения в SQL на стороне PHP. Со значением false подготовка уходит на сервер MySQL, что даёт корректную типизацию параметров и защиту от целого класса ошибок с экранированием. Для новых проектов ставьте false.
Шаг 3. Выполняем запрос
Никогда не склеивайте пользовательские данные в строку SQL. Для подстановки значений используйте подготовленные запросы с плейсхолдерами. Добавьте это в конец db.php:
// Выборка с параметром
$sql = 'SELECT id, name, price FROM products WHERE price > :min_price';
$stmt = $pdo->prepare($sql);
$stmt->execute(['min_price' => 1000]);
$rows = $stmt->fetchAll();
foreach ($rows as $row) {
echo $row['id'] . ' — ' . $row['name'] . "\n";
}Плейсхолдер :min_price — это именованный параметр. PDO сам подставит значение безопасно. Если запрос вернул строки, вы увидите их в консоли. Если таблицы products нет — получите исключение с текстом об отсутствующей таблице, что как раз и настроено на шаге 2.
Вставка данных и полученный id
$sql = 'INSERT INTO products (name, price) VALUES (:name, :price)';
$stmt = $pdo->prepare($sql);
$stmt->execute([
'name' => 'Кофемолка',
'price' => 2490,
]);
// id только что вставленной строки
$newId = $pdo->lastInsertId();
echo "Добавлена строка с id $newId\n";Если не получилось
Пять ошибок, которые видят чаще всего, и что с ними делать:
- SQLSTATE[HY000] [2002] Connection refused — MySQL не запущен или слушает другой хост/порт. Проверьте, что сервер работает, и что хост в DSN совпадает с реальным. На некоторых системах
localhostведёт к сокету, а127.0.0.1— к TCP; если сомневаетесь, пробуйте127.0.0.1. - SQLSTATE[HY000] [1045] Access denied for user — неверный логин или пароль, либо у пользователя нет прав на эту базу. Сверьте доступы и права в MySQL.
- SQLSTATE[HY000] [1049] Unknown database — базы с таким
dbnameне существует. Создайте её или исправьте имя в DSN. - could not find driver — расширение
pdo_mysqlне включено. Вернитесь к разделу «Что нужно иметь до начала». - Кракозябры вместо русских букв — забыли
charset=utf8mb4в DSN, либо сама таблица создана в другой кодировке. Проверьте оба места.
Что дальше
Рабочее подключение — только старт. Дальше стоит посмотреть в сторону: не открывать новое соединение на каждый запрос, а переиспользовать один объект $pdo в рамках запроса; в проде не выводить getMessage() пользователю, а писать в лог; обернуть несколько связанных INSERT в транзакцию через beginTransaction() и commit(). Транзакции и пулы соединений — отдельная тема, здесь мы разобрали только первое подключение и базовый запрос.
Разбор научной статьи: Сложный текст — понятным языком, с терминами
Спросить за 12 ₽Источники: PHP Manual: PDO — MySQL (PDO_MYSQL) DSN, PHP Manual: PDO::__construct
Частые вопросы
У меня PHP 7.4, а не 8.x — код заработает?
Что выбрать в DSN — localhost или 127.0.0.1?
В чём разница между utf8 и utf8mb4?
Нужно ли закрывать соединение вручную?
Почему нельзя просто подставить переменную в строку запроса?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.