Работа с базами данных: PDO и MySQLi для подключения
Основные методы подключения к базе данных в PHP
Подключение к базе данных - ключевой этап при создании динамических веб-приложений. В PHP существует несколько способов установить соединение с СУБД. Каждый из них имеет свои особенности, преимущества и ограничения. Ниже рассматриваются наиболее распространённые варианты с примерами кода и пояснениями.
Как обеспечить универсальное и безопасное подключение?
PDO (PHP Data Objects) - рекомендуемое расширение, предоставляющее единый интерфейс для работы с разными СУБД. Оно поддерживает подготовленные запросы, что защищает от SQL-инъекций, и позволяет гибко управлять обработкой ошибок.
$host = 'localhost';
$dbname = 'mydb';
$username = 'root';
$password = '';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Подключение успешно";
} catch (PDOException $e) {
echo "Ошибка подключения: " . $e->getMessage();
}
Пояснение: в DSN указываются тип СУБД (mysql), хост, имя базы и кодировка. Атрибут ERRMODE_EXCEPTION заставляет PDO выбрасывать исключения при ошибках, что упрощает отладку.
Типичные проблемы и их решения:
- „Could not find driver“ - не установлен драйвер PDO для нужной СУБД (например,
pdo_mysql). Установите его через менеджер пакетов. - „Access denied for user“ - неверное имя пользователя или пароль. Проверьте учётные данные и права доступа.
- „Base not found“ - указанная база данных не существует. Создайте её или проверьте имя.
Как подключиться через MySQLi в объектно-ориентированном стиле?
Расширение MySQLi работает исключительно с MySQL, но предоставляет как объектно-ориентированный, так и процедурный интерфейс.
$mysqli = new mysqli('localhost', 'root', '', 'mydb');
if ($mysqli->connect_error) {
die('Ошибка подключения: ' . $mysqli->connect_error);
}
echo "Подключение успешно";
После создания объекта проверяется свойство connect_error. Если оно не пусто, соединение не установлено.
Распространённые ошибки:
- Если не передан порт, MySQLi использует стандартный 3306. Для другого порта добавьте пятый параметр:
new mysqli('host', 'user', 'pass', 'db', 3307). - В PHP 8+ многие настройки MySQLi по умолчанию вызывают исключения, но для совместимости лучше явно задать режим отчёта об ошибках:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
Как выполнить подключение через MySQLi процедурным способом?
Процедурный стиль использует функции mysqli_connect() и mysqli_connect_error().
$connection = mysqli_connect('localhost', 'root', '', 'mydb');
if (!$connection) {
die('Ошибка подключения: ' . mysqli_connect_error());
}
echo "Подключение успешно";
Функция возвращает ресурс соединения или false при неудаче. Этот стиль чаще встречается в старом коде, но всё ещё допустим.
При использовании mysqli_connect() ошибка соединения не вызывает исключение, поэтому обязательна проверка возвращаемого значения.
Как подключиться к SQLite или PostgreSQL через PDO?
PDO позволяет легко переключаться между СУБД, меняя только DSN. Примеры:
// SQLite
$pdo = new PDO('sqlite:/path/to/database.db');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Подключение к SQLite выполнено";
// PostgreSQL
$dsn = 'pgsql:host=localhost;dbname=mydb';
$pdo = new PDO($dsn, 'user', 'pass');
echo "Подключение к PostgreSQL выполнено";
Для SQLite не требуется имя пользователя и пароль, а файл базы создаётся автоматически, если его нет.
Не забудьте установить соответствующий драйвер PDO: pdo_sqlite, pdo_pgsql и т.д. Список доступных драйверов можно получить через PDO::getAvailableDrivers().
Как организовать параметры подключения в конфигурационном файле?
Вынесение настроек в отдельный файл улучшает сопровождение и безопасность кода.
// config.php
return [
'host' => 'localhost',
'dbname' => 'mydb',
'user' => 'root',
'pass' => '',
'charset' => 'utf8mb4'
];
В основном файле подключения:
$config = require 'config.php';
$dsn = "mysql:host={$config['host']};dbname={$config['dbname']};charset={$config['charset']}";
$pdo = new PDO($dsn, $config['user'], $config['pass']);
Такой подход упрощает изменение параметров для разных окружений (локальное, тестовое, продакшн).
Не храните конфигурационные файлы в публичной директории веб-сервера. Размещайте их выше корня документа или защищайте через .htaccess.
Выбор конкретного метода зависит от проекта. Для универсальности и безопасности предпочтителен PDO. MySQLi подходит, если приложение жёстко привязано к MySQL. Конфигурационные файлы полезны в любом случае.
Расширенные примеры подключения
Пример 1: PDO с полной настройкой и обработкой исключений
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8mb4';
$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, 'root', '', $options);
echo "Подключение через PDO с настройками выполнено";
} catch (PDOException $e) {
echo "Ошибка: " . $e->getMessage();
}
Подключение через PDO с настройками выполнено
Здесь явно задан режим выборки ассоциативных массивов и отключена эмуляция подготовленных запросов (рекомендуется для MySQL).
Пример 2: MySQLi с подготовленным запросом SELECT
$mysqli = new mysqli('localhost', 'root', '', 'testdb');
if ($mysqli->connect_error) {
die('Ошибка: ' . $mysqli->connect_error);
}
$stmt = $mysqli->prepare('SELECT id, name FROM users WHERE status = ?');
$status = 'active';
$stmt->bind_param('s', $status);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['id'] . ' - ' . $row['name'] . '<br>';
}
$stmt->close();
$mysqli->close();
1 - Иван
2 - Мария
Подготовленные запросы защищают от SQL-инъекций, а bind_param указывает типы переменных.
Пример 3: PDO с SQLite и создание таблицы
$pdo = new PDO('sqlite:test.db');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)');
echo "Таблица создана";
$pdo->exec("INSERT INTO users (name) VALUES ('Анна')");
echo "Запись добавлена";
$result = $pdo->query('SELECT * FROM users');
foreach ($result as $row) {
echo $row['id'] . ' ' . $row['name'] . '<br>';
}
Таблица создана Запись добавлена 1 Анна
SQLite не требует предварительного создания базы - файл появляется автоматически.
Пример 4: Проверка доступных драйверов PDO
$drivers = PDO::getAvailableDrivers();
echo 'Доступные драйверы: ' . implode(', ', $drivers);
Доступные драйверы: mysql, pgsql, sqlite, sqlsrv
Этот список помогает убедиться, что необходимые расширения установлены.
Пример 5: Конфигурационный файл, возвращающий массив
// db_config.php
return [
'dsn' => 'mysql:host=localhost;dbname=shop;charset=utf8mb4',
'user' => 'shop_user',
'pass' => 'secret',
];
// connect.php
$config = require 'db_config.php';
try {
$pdo = new PDO($config['dsn'], $config['user'], $config['pass']);
echo "Подключение к базе 'shop' выполнено";
} catch (PDOException $e) {
echo "Ошибка: " . $e->getMessage();
}
Подключение к базе 'shop' выполнено
Такой подход позволяет легко менять параметры для разных окружений, не редактируя основной код.
Пример 6: MySQLi с установкой кодировки и отчётом об ошибках
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'root', '', 'testdb');
$mysqli->set_charset('utf8mb4');
echo "Кодировка соединения: " . $mysqli->character_set_name();
$result = $mysqli->query('SELECT VERSION()');
$row = $result->fetch_row();
echo "Версия MySQL: " . $row[0];
Кодировка соединения: utf8mb4 Версия MySQL: 8.0.34
Установка кодировки через set_charset() предпочтительнее, чем выполнение SQL-запроса SET NAMES.