Реализация запросов к базе данных в PHP с помощью PDO и MySQLi
Способы выполнения запросов к базе данных в PHP
Как выполнить безопасный запрос с параметрами?
Наиболее эффективное решение - использование PDO с подготовленными запросами. PDO поддерживает разные СУБД, защищает от SQL-инъекций и даёт единый интерфейс.
$dsn = 'mysql:host=localhost;dbname=test;charset=utf8';
$user = 'root';
$password = '';
try {
$pdo = new PDO($dsn, $user, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die('Ошибка подключения: ' . $e->getMessage());
}
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute([':email' => 'user@example.com']);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
print_r($user);
Пояснение: PDO::prepare создаёт объект PDOStatement. Вызов execute передаёт значения параметров. Режим FETCH_ASSOC возвращает ассоциативный массив.
Типичная ошибка - неправильный DSN или отсутствие драйвера PDO для MySQL. Для устранения проверяется наличие расширения php_pdo_mysql в php.ini. Ошибка синтаксиса SQL вызывает исключение при включённом ERRMODE_EXCEPTION.
Как использовать объектно-ориентированный MySQLi?
MySQLi предлагает объектный интерфейс:
$mysqli = new mysqli('localhost', 'root', '', 'test');
if ($mysqli->connect_error) {
die('Ошибка подключения: ' . $mysqli->connect_error);
}
$stmt = $mysqli->prepare('SELECT * FROM users WHERE email = ?');
$stmt->bind_param('s', $email);
$email = 'user@example.com';
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
print_r($user);
$stmt->close();
$mysqli->close();
Пояснение: bind_param задаёт типы параметров ('s' - строка). get_result возвращает объект результата.
Ошибки возникают при неверных учётных данных или отсутствии прав. Для отладки используется свойство $mysqli->error.
Как выполнить запрос процедурным способом MySQLi?
Процедурный стиль использует функции mysqli_*:
$link = mysqli_connect('localhost', 'root', '', 'test');
if (!$link) {
die('Ошибка подключения: ' . mysqli_connect_error());
}
$email = 'user@example.com';
$stmt = mysqli_prepare($link, 'SELECT * FROM users WHERE email = ?');
mysqli_stmt_bind_param($stmt, 's', $email);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$user = mysqli_fetch_assoc($result);
print_r($user);
mysqli_stmt_close($stmt);
mysqli_close($link);
Пояснение аналогично объектному, но функции не являются методами класса.
Путаница между объектным и процедурным стилем приводит к ошибкам. Рекомендуется придерживаться одного стиля в проекте.
Стоит ли использовать mysql_* функции?
Расширение mysql_* удалено из PHP 7.0. Использовать его не рекомендуется. В проектах с устаревшей версией PHP необходима миграция на PDO или MySQLi.
Ошибка - вызов несуществующей функции mysql_connect в PHP 7+.
Продвинутые техники выполнения запросов
Транзакции в PDO
Транзакции обеспечивают атомарность операций:
$pdo->beginTransaction();
try {
$pdo->exec('UPDATE accounts SET balance = balance - 100 WHERE id = 1');
$pdo->exec('UPDATE accounts SET balance = balance + 100 WHERE id = 2');
$pdo->commit();
echo 'Транзакция выполнена';
} catch (PDOException $e) {
$pdo->rollBack();
echo 'Ошибка: ' . $e->getMessage();
}
Транзакция выполнена
Пояснение: beginTransaction начинает транзакцию. При ошибке вызывается rollBack.
Получение одного значения через fetchColumn
$stmt = $pdo->query('SELECT COUNT(*) FROM users');
$count = $stmt->fetchColumn();
echo 'Количество пользователей: ' . $count;
Количество пользователей: 42
Вставка нескольких строк в цикле с prepared statement
$stmt = $pdo->prepare('INSERT INTO users (name, email) VALUES (:name, :email)');
$users = [
['name' => 'Alice', 'email' => 'alice@example.com'],
['name' => 'Bob', 'email' => 'bob@example.com'],
];
foreach ($users as $user) {
$stmt->execute($user);
}
echo 'Вставлено строк: ' . count($users);
Вставлено строк: 2
Динамический IN() с помощью плейсхолдеров
$ids = [1, 2, 3];
$placeholders = implode(',', array_fill(0, count($ids), '?'));
$stmt = $pdo->prepare("SELECT * FROM users WHERE id IN ($placeholders)");
$stmt->execute($ids);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($result);
Array
(
[0] => Array ( [id] => 1 [name] => Alice ... )
[1] => Array ( [id] => 2 [name] => Bob ... )
[2] => Array ( [id] => 3 [name] => Charlie ... )
)
Работа с датами и форматирование
$stmt = $pdo->prepare('SELECT id, DATE_FORMAT(created_at, \'%d.%m.%Y\') AS formatted_date FROM posts WHERE id = ?');
$stmt->execute([1]);
$post = $stmt->fetch(PDO::FETCH_ASSOC);
echo $post['formatted_date'];
25.03.2025
Логирование ошибок запросов
try {
$pdo->query('SELECT * FROM non_existent_table');
} catch (PDOException $e) {
error_log('Ошибка SQL: ' . $e->getMessage());
echo 'Произошла ошибка, детали записаны в лог.';
}
Произошла ошибка, детали записаны в лог.