Базы данных PHP: полные примеры скриптов и решений
Основы работы с базами данных в PHP
При разработке веб приложений на PHP часто требуется взаимодействие с базами данных. Статья содержит примеры подключения, выполнения запросов и обработки результатов с использованием разных расширений. Основное внимание уделено безопасным методам и устранению типичных ошибок.
Как организовать универсальное и безопасное взаимодействие с различными СУБД?
Наиболее эффективным решением является использование расширения PDO (PHP Data Objects). PDO предоставляет единый интерфейс для работы с MySQL, PostgreSQL, SQLite, MSSQL и другими СУБД, поддерживает подготовленные выражения, транзакции и обработку ошибок через исключения.
<?php
$dsn = 'mysql:host=localhost;dbname=test;charset=utf8mb4';
$user = 'root';
$pass = '';
$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();
}
?>
примеры баз данных php (примеры баз данных в php)
Параметр dsn содержит тип СУБД, хост, имя базы и кодировку. Опции ERRMODE_EXCEPTION и FETCH_ASSOC включают исключения при ошибках и возврат ассоциативных массивов по умолчанию.
Типичная ошибка: неправильное указание имени драйвера (например, 'mysql' вместо 'mysqli') приводит к исключению PDOException. Решение: проверить, что нужный драйвер установлен через phpinfo().
Подготовленный запрос с параметрами позволяет избежать SQL инъекций:
<?php
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute(['email' => 'user@example.com']);
$user = $stmt->fetch();
?>
Именованные плейсхолдеры (:email) или вопросительные знаки автоматически экранируют данные.
Каким образом можно работать с MySQL через MySQLi?
Расширение MySQLi поддерживает как объектный, так и процедурный стиль. Для новых проектов рекомендуется объектный.
<?php
$mysqli = new mysqli('localhost', 'root', '', 'test');
if ($mysqli->connect_error) {
die('Ошибка подключения: ' . $mysqli->connect_error);
}
$result = $mysqli->query('SELECT id, name FROM users');
while ($row = $result->fetch_assoc()) {
echo $row['name'];
}
$mysqli->close();
?>
Проблема:
Использование query() для прямых строк без экранирования приводит к уязвимостям. Для безопасной вставки применяйте prepare() и bind_param().
<?php
$stmt = $mysqli->prepare('INSERT INTO users (name, email) VALUES (?, ?)');
$stmt->bind_param('ss', $name, $email);
$name = 'Иван';
$email = 'ivan@example.com';
$stmt->execute();
$stmt->close();
?>
Как подключиться к SQLite базе данных с помощью PDO?
SQLite удобна для хранения небольших данных без отдельного сервера. Подключение осуществляется через DSN с указанием пути к файлу.
<?php
$pdo = new PDO('sqlite:/tmp/test.db');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, text TEXT)');
$stmt = $pdo->prepare('INSERT INTO notes (text) VALUES (:text)');
$stmt->execute(['text' => 'Запись']);
?>
Ошибка SQLSTATE[HY000] General error возникает при невозможности создать файл базы из за прав доступа. Решение: указать путь в каталоге, доступном для записи веб серверу, и установить права 755 на папку.
Какие альтернативные способы подключения к MySQL существуют?
Устаревшее расширение mysql_* удалено из PHP 7, но его можно встретить в legacy проектах. Использовать не рекомендуется.
<?php
$link = mysql_connect('localhost', 'root', '');
mysql_select_db('test', $link);
$result = mysql_query('SELECT * FROM users');
while ($row = mysql_fetch_assoc($result)) {
echo $row['name'];
}
mysql_close($link);
?>
Отсутствие экранирования и уязвимость к SQL инъекциям. Для безопасной работы даже в старых версиях следует использовать mysql_real_escape_string(). Рекомендуется мигрировать на PDO или MySQLi.
Расширенные примеры работы с базами данных в PHP
Пример 1. Выборка данных с пагинацией и JOIN
<?php
$pdo = new PDO('mysql:host=localhost;dbname=blog;charset=utf8mb4', 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$page = 2;
$limit = 5;
$offset = ($page - 1) * $limit;
$sql = 'SELECT p.title, u.name AS author, p.created_at
FROM posts p
JOIN users u ON p.user_id = u.id
ORDER BY p.created_at DESC
LIMIT :limit OFFSET :offset';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();
$posts = $stmt->fetchAll();
foreach ($posts as $post) {
echo $post['title'] . ' - ' . $post['author'] . '\n';
}
?>
Новости недели - Администратор Важное обновление - Модератор ...
Пояснение:
Используется bindValue() для явного указания типа параметра (INT). Это предотвращает ошибки неявного преобразования.
Пример 2. Транзакции с откатом при ошибке
<?php
$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();
} catch (PDOException $e) {
$pdo->rollBack();
echo 'Перевод отменен: ' . $e->getMessage();
}
?>
Перевод выполнен успешно
Если один из запросов завершается неудачей, все изменения отменяются.
Пример 3. Массовая вставка записей с использованием подготовленного выражения
<?php
$data = [
['name' => 'Товар1', 'price' => 100],
['name' => 'Товар2', 'price' => 200],
['name' => 'Товар3', 'price' => 300],
];
$stmt = $pdo->prepare('INSERT INTO products (name, price) VALUES (:name, :price)');
foreach ($data as $row) {
$stmt->execute($row);
}
echo 'Вставлено ' . count($data) . ' записей';
?>
Вставлено 3 записей
Позволяет эффективно вставлять много строк, не пересоздавая выражение.
Пример 4. Использование разных fetch режимов
<?php
$stmt = $pdo->query('SELECT id, name FROM users');
// Ассоциативный массив
$usersAssoc = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Объект
$usersObj = $stmt->fetchAll(PDO::FETCH_OBJ);
// Нумерованный массив
$usersNum = $stmt->fetchAll(PDO::FETCH_NUM);
?>
Выбор режима зависит от удобства дальнейшей обработки.
Пример 5. Работа с NULL и значениями по умолчанию
<?php
$stmt = $pdo->prepare('INSERT INTO logs (action, ip) VALUES (:action, :ip)');
$stmt->execute([
'action' => 'login',
'ip' => $_SERVER['REMOTE_ADDR'] ?? null
]);
?>
PDO корректно обрабатывает NULL, отображая его в базе как NULL, если столбец допускает.