MySQL сервер и PHP: подключение, запросы и управление данными
Основные способы взаимодействия PHP с MySQL
Как наиболее эффективно подключаться к MySQL и выполнять запросы с помощью PDO?
Расширение PDO (PHP Data Objects) предоставляет универсальный интерфейс для работы с базами данных. Оно поддерживает подготовленные выражения, транзакции и обработку ошибок через исключения. Это решение подходит для проектов, где требуется гибкость, безопасность и совместимость с разными СУБД.
Пример подключения к MySQL через PDO:
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8mb4';
$user = 'root';
$pass = 'password';
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
echo 'Подключение успешно';
} catch (PDOException $e) {
echo 'Ошибка подключения: ' . $e->getMessage();
}
В коде используется DSN (Data Source Name), который содержит тип базы данных, хост, имя базы и кодировку. Опции ATTR_ERRMODE и ATTR_DEFAULT_FETCH_MODE задают режим ошибок (исключения) и формат выборки (ассоциативный массив).
Типичные проблемы и их решения:
- Ошибка "could not find driver" - не установлено расширение PHP для MySQL (php_pdo_mysql). Решение: установить и включить в php.ini.
- Ошибка подключения (Access denied) - неверные учётные данные или отсутствие прав. Проверить имя пользователя, пароль и привилегии.
- Проблемы с кодировкой - рекомендуется указывать charset=utf8mb4 в DSN, чтобы избежать искажения символов.
Как использовать расширение mysqli для работы с MySQL?
Расширение mysqli (MySQL Improved) существует в двух стилях: процедурном и объектно-ориентированном. Оно также поддерживает подготовленные выражения, но привязано только к MySQL.
Пример объектного стиля mysqli:
$mysqli = new mysqli('localhost', 'root', 'password', 'testdb');
if ($mysqli->connect_error) {
die('Ошибка подключения: ' . $mysqli->connect_error);
}
$result = $mysqli->query('SELECT * FROM users');
while ($row = $result->fetch_assoc()) {
echo $row['name'];
}
$mysqli->close();
В процедурном стиле функции имеют префикс mysqli_ (например, mysqli_connect(), mysqli_query()).
Проблемы mysqli:
- SQL-инъекции - при прямом построении запросов без экранирования. Решение: использовать подготовленные выражения или real_escape_string().
- Закрытие соединения - в долгих скриптах необходимо явно вызывать close().
Что такое устаревшее расширение mysql и почему от него отказались?
Расширение mysql было удалено в PHP 7.0. Оно не поддерживало подготовленные выражения, транзакции и было небезопасным. Использовать его в новых проектах нельзя.
Как автоматически подключаться к базе данных через конфигурационный файл?
Можно создать отдельный файл config.php с настройками и подключать его в скриптах:
<?
// config.php
define('DB_HOST', 'localhost');
define('DB_NAME', 'testdb');
define('DB_USER', 'root');
define('DB_PASS', 'password');
define('DB_CHARSET', 'utf8mb4');
?>
Затем в основном файле:
require 'config.php';
$dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET;
$pdo = new PDO($dsn, DB_USER, DB_PASS);
Цель - централизованное управление настройками и упрощение поддержки.
Расширенные примеры работы с MySQL в PHP
Пример 1: Подготовленные выражения с PDO (защита от инъекций)
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute(['email' => 'user@example.com']);
$user = $stmt->fetch();
print_r($user);
Array
(
[id] => 1
[name] => Иван
[email] => user@example.com
)
Пример 2: Транзакции в PDO
try {
$pdo->beginTransaction();
$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();
}
(нет вывода при успехе, иначе сообщение об ошибке)
Пример 3: Пакетная вставка через PDO с заполнителями
$data = [
['name' => 'Анна', 'email' => 'anna@test.com'],
['name' => 'Петр', 'email' => 'petr@test.com'],
];
$stmt = $pdo->prepare('INSERT INTO users (name, email) VALUES (:name, :email)');
foreach ($data as $row) {
$stmt->execute($row);
}
echo 'Вставлено ' . count($data) . ' записей';
Вставлено 2 записей
Пример 4: Использование mysqli с подготовленными выражениями (объектный стиль)
$stmt = $mysqli->prepare('SELECT id, name FROM users WHERE email = ?');
$email = 'user@example.com';
$stmt->bind_param('s', $email);
$stmt->execute();
$stmt->bind_result($id, $name);
while ($stmt->fetch()) {
echo "ID: $id, Name: $name\n";
}
$stmt->close();
ID: 1, Name: Иван
Пример 5: Работа с хранимыми процедурами в PDO
$stmt = $pdo->prepare('CALL get_users_by_status(:status)');
$stmt->execute(['status' => 'active']);
$users = $stmt->fetchAll();
foreach ($users as $user) {
echo $user['name'] . '
';
}
Иван
Анна
Пример 6: Обработка ошибок и логирование в PDO
try {
$pdo->query('INVALID SQL');
} catch (PDOException $e) {
error_log('SQL error: ' . $e->getMessage(), 0);
echo 'Произошла ошибка запроса. Подробности в логах.';
}
Произошла ошибка запроса. Подробности в логах.