Подключение к MySQL средствами PHP: практическое руководство
Варианты подключения к MySQL из PHP
Каким образом организовать надёжное и безопасное соединение с MySQL, поддерживающее работу с несколькими драйверами и подготовленные запросы?
Наиболее универсальным решением является расширение PDO (PHP Data Objects). Оно предоставляет единый интерфейс для работы с разными СУБД, включая MySQL, и позволяет легко переключаться между ними без изменения основного кода.
Пример подключения с помощью PDO:
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8mb4';
$user = 'root';
$password = '';
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
$pdo = new PDO($dsn, $user, $password, $options);
Phpmyadmin php (phpmyadmin в php)
В строке DSN указываются хост, имя базы данных и кодировка. Опция ERRMODE_EXCEPTION заставляет PDO выбрасывать исключения при ошибках, что упрощает отладку. Атрибут DEFAULT_FETCH_MODE задаёт формат возвращаемых данных (в примере - ассоциативный массив).
Типичные ошибки при использовании PDO:
- SQLSTATE[HY000] [1045] Access denied - неверное имя пользователя или пароль; следует проверить учётные данные в файле конфигурации.
- SQLSTATE[HY000] [2002] Connection refused - MySQL-сервер не запущен или указан неправильный порт; проверьте службу MySQL и номер порта (по умолчанию 3306).
- SQLSTATE[42000] Syntax error - ошибка в SQL-запросе; используйте подготовленные выражения для избежания синтаксических проблем с кавычками.
Цель использования PDO: создание переносимого кода, поддержка разных СУБД, защита от SQL-инъекций через подготовленные запросы.
Как установить соединение с MySQL через MySQLi в объектно-ориентированном стиле?
Расширение MySQLi (MySQL improved) предлагает как процедурный, так и ООП-интерфейс. ООП-вариант более современный и удобный для проектов с классами.
$mysqli = new mysqli('localhost', 'root', '', 'testdb');
if ($mysqli->connect_error) {
die('Ошибка подключения: ' . $mysqli->connect_error);
}
$mysqli->set_charset('utf8mb4');
Php having (оператор having в sql (php))
Метод set_charset задаёт кодировку соединения. Проверка connect_error необходима для обработки неудачного подключения.
Частая проблема: сообщение Call to undefined method mysqli::set_charset() - возможно, используется устаревшая версия PHP (ниже 5.0.5). Решение - обновить PHP или применить SQL-запрос SET NAMES 'utf8mb4'.
Цель: работа только с MySQL, но с полным набором возможностей (множественные запросы, транзакции, объектный стиль).
Каким образом выполнить подключение к MySQL с помощью процедурного MySQLi?
Процедурный вариант подходит для простых скриптов или для тех, кто привык к старому mysql-расширению.
$link = mysqli_connect('localhost', 'root', '', 'testdb');
if (!$link) {
die('Ошибка: ' . mysqli_connect_error());
}
mysqli_set_charset($link, 'utf8mb4');
Php sql (php и sql)
Функция mysqli_connect возвращает ресурс соединения. Все последующие операции выполняются через этот ресурс.
Распространённая ошибка: забыть вызвать mysqli_set_charset, что приводит к некорректному отображению кириллицы. Решение - всегда явно указывать кодировку после подключения.
Цель: быстрый переход с устаревшего mysql на поддерживаемое расширение без изменения архитектуры проекта.
Почему старое расширение mysql (deprecated) не рекомендуется и как от него отказаться?
Расширение mysql_* было удалено из PHP 7.0. Использовать его нельзя. Необходимо заменить все вызовы mysql_connect(), mysql_query() и т.д. на аналоги из MySQLi или PDO.
Пример замены старого кода на PDO:
// Старый код:
// $link = mysql_connect('localhost', 'root', '');
// mysql_select_db('testdb', $link);
// Новый код:
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8mb4';
$pdo = new PDO($dsn, 'root', '');
Ошибка: при попытке использовать mysql_connect() в PHP 7+ возникает Fatal error: Uncaught Error: Call to undefined function mysql_connect(). Решение - полный переход на MySQLi или PDO.
Цель: безопасность и совместимость с современными версиями PHP.
Расширенные примеры соединения MySQL с PHP
Пример 1: PDO с обработкой ошибок и транзакцией
Полный скрипт, демонстрирующий подключение, выполнение транзакции и отлов исключений:
<?php
try {
$dsn = 'mysql:host=localhost;dbname=shop;charset=utf8mb4';
$pdo = new PDO($dsn, 'root', '', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_AUTOCOMMIT => false,
]);
$pdo->beginTransaction();
$stmt = $pdo->prepare('INSERT INTO products (name, price) VALUES (?, ?)');
$stmt->execute(['Телефон', 25000]);
$stmt->execute(['Ноутбук', 75000]);
$pdo->commit();
} catch (PDOException $e) {
$pdo->rollBack();
echo 'Ошибка: ' . $e->getMessage();
}
?>
Результат выполнения: в таблицу products будут добавлены две записи. Если на втором execute произойдёт ошибка (например, дублирование уникального поля), транзакция откатится, и ни одна запись не будет вставлена.
(нет вывода на экран, записи добавлены в БД)
Пример 2: MySQLi с подготовленными запросами и получением данных
Использование подготовленного выражения для безопасной выборки по идентификатору:
$mysqli = new mysqli('localhost', 'root', '', 'blog');
if ($mysqli->connect_error) {
die('Ошибка: ' . $mysqli->connect_error);
}
$mysqli->set_charset('utf8mb4');
$id = 10;
$stmt = $mysqli->prepare('SELECT title, content FROM articles WHERE id = ?');
$stmt->bind_param('i', $id);
$stmt->execute();
$result = $stmt->get_result();
$article = $result->fetch_assoc();
echo 'Заголовок: ' . $article['title'] . '\n';
echo 'Содержание: ' . $article['content'];
$stmt->close();
$mysqli->close();
Результат (зависит от данных в таблице):
Заголовок: Введение в PHP Содержание: PHP - скриптовый язык программирования...
Пояснение: метод bind_param привязывает переменную к параметру. Буква 'i' указывает тип integer. Это предотвращает SQL-инъекции.
Пример 3: PDO с нестандартными настройками (сокет, постоянное соединение)
Подключение через Unix-сокет (часто используется на локальном сервере) и включение постоянного соединения для уменьшения накладных расходов:
$dsn = 'mysql:unix_socket=/var/run/mysqld/mysqld.sock;dbname=mydb;charset=utf8';
$pdo = new PDO($dsn, 'user', 'pass', [
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
Постоянное соединение сохраняется между запросами, но может вызвать блокировки в некоторых сценариях. Следует применять с осторожностью.
Результат: успешное подключение без указания хоста и порта, через сокет.
(соединение установлено)
Пример 4: Чтение параметров подключения из файла конфигурации
Хранение учётных данных в отдельном файле config.ini:
; config.ini
[database]
host = localhost
username = dbuser
password = secret
charset = utf8mb4
$config = parse_ini_file('config.ini', true);
$db = $config['database'];
$dsn = "mysql:host={$db['host']};dbname=mydb;charset={$db['charset']}";
$pdo = new PDO($dsn, $db['username'], $db['password']);
Такой подход упрощает развёртывание на разных серверах. Проблема: файл ini может быть доступен извне - размещайте его вне DocumentRoot.
Дополнительно: для повышения безопасности пароли можно хранить в переменных окружения и получать через getenv().