Разработка на PHP и MySQL: практические примеры и лучшие практики

Раздел: Веб-разработка -> Разработка веб-приложений на PHP

Создание сайтов на PHP и MySQL: практическое руководство

Как обеспечить безопасное и эффективное взаимодействие с базой данных?

Основное решение: использование PDO с подготовленными запросами

PDO (PHP Data Objects) - это расширение для работы с базами данных, которое предоставляет единый интерфейс для разных СУБД. Оно позволяет выполнять подготовленные запросы, что предотвращает SQL-инъекции и улучшает производительность при многократном выполнении однотипных запросов.


// Подключение к MySQL через PDO
$host = 'localhost';
$dbname = 'test';
$user = 'root';
$password = '';

try {
    $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $user, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die('Ошибка подключения: ' . $e->getMessage());
}

// Подготовленный запрос INSERT
$sql = 'INSERT INTO users (name, email) VALUES (:name, :email)';
$stmt = $pdo->prepare($sql);
$stmt->execute([':name' => 'Иван', ':email' => 'ivan@example.com']);
  

Php mysql сайты (сайты на php и mysql)

Типичные ошибки и их решение:

  • Ошибка подключения: неверные параметры host, dbname, user или password. Проверьте доступность сервера MySQL и правильность учётных данных.
  • SQL-инъекция: если данные не экранируются. Использование подготовленных запросов полностью исключает эту проблему.
  • Ошибка синтаксиса SQL: проверьте запрос в консоли MySQL перед использованием.

Цели использования:

  • Безопасная передача пользовательских данных в запросы.
  • Унификация кода для разных БД (например, MySQL и PostgreSQL).
  • Удобство обработки ошибок через исключения.

Как выполнить запрос к MySQL с помощью mysqli (процедурный стиль)?

Процедурный mysqli - классический способ, который подходит для простых проектов. Он использует функции, а не объекты.


$link = mysqli_connect('localhost', 'root', '', 'test');
if (!$link) {
    die('Ошибка соединения: ' . mysqli_connect_error());
}

$result = mysqli_query($link, 'SELECT * FROM users');
while ($row = mysqli_fetch_assoc($result)) {
    echo $row['name'] . '
'; }

динамический php (динамические возможности php)

Проблемы:

  • Ручное экранирование (mysqli_real_escape_string) увеличивает риск ошибок.
  • Нет поддержки исключений - нужно вручную проверять ошибки.

Когда использовать:

Для быстрого прототипирования или в легаси-проектах, где уже используется процедурный подход.

Как работать с MySQL через mysqli в объектно-ориентированном стиле?

Объектно-ориентированный mysqli предоставляет классы и методы, делая код более структурированным.


$mysqli = new mysqli('localhost', 'root', '', 'test');
if ($mysqli->connect_error) {
    die('Ошибка: ' . $mysqli->connect_error);
}

$stmt = $mysqli->prepare('INSERT INTO users (name) VALUES (?)');
$stmt->bind_param('s', $name);
$name = 'Петр';
$stmt->execute();
  

Типичная ошибка:

Забывают вызвать bind_param() после prepare. Это приводит к ошибке "No statement resource".

Сильные стороны:

Лучше процедурного стиля, но уступает PDO в переносимости.

Как использовать PDO для выборки данных с JOIN?

Пример более сложного запроса с объединением таблиц.


$sql = 'SELECT u.name, o.order_date FROM users u JOIN orders o ON u.id = o.user_id WHERE u.status = :status';
$stmt = $pdo->prepare($sql);
$stmt->execute([':status' => 'active']);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($result as $row) {
    echo "Пользователь {$row['name']} заказал {$row['order_date']}
"; }

Проблема:

Если JOIN возвращает дубли имён полей, то fetchAll(PDO::FETCH_ASSOC) перезаписывает значения. Решение - использовать алиасы в SQL.

Заключение

Для современной веб-разработки на PHP и MySQL рекомендуется использовать PDO из-за его безопасности, гибкости и поддержки разных СУБД. Варианты с mysqli подходят для унаследованных проектов или когда требуется максимальная производительность без слоя абстракции.

Расширенные примеры работы с PHP и MySQL

Пример 1: Регистрация пользователя с хэшированием пароля

Пример

// registration.php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';

if (empty($name) || empty($email) || empty($password)) {
    die('Заполните все поля');
}

// Хэширование пароля
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);

$sql = 'INSERT INTO users (name, email, password) VALUES (:name, :email, :password)';
$stmt = $pdo->prepare($sql);
$stmt->execute([
    ':name' => $name,
    ':email' => $email,
    ':password' => $hashedPassword
]);

echo 'Пользователь зарегистрирован';
При успешном выполнении: Пользователь зарегистрирован
При дублировании email: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry...

Пример 2: Авторизация и проверка пароля

Пример

// login.php
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';

$stmt = $pdo->prepare('SELECT id, password FROM users WHERE email = :email');
$stmt->execute([':email' => $email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);

if ($user && password_verify($password, $user['password'])) {
    session_start();
    $_SESSION['user_id'] = $user['id'];
    echo 'Вход выполнен';
} else {
    echo 'Неверный email или пароль';
}
При верных данных: Вход выполнен
При неверных: Неверный email или пароль

Пример 3: Постраничный вывод записей (пагинация)

Пример

$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$perPage = 10;
$offset = ($page - 1) * $perPage;

// Общее количество записей
$countStmt = $pdo->query('SELECT COUNT(*) FROM articles');
$total = $countStmt->fetchColumn();
$totalPages = ceil($total / $perPage);

// Выборка с лимитом
$stmt = $pdo->prepare('SELECT id, title FROM articles ORDER BY id DESC LIMIT :limit OFFSET :offset');
$stmt->bindValue(':limit', $perPage, PDO::PARAM_INT);
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();
$articles = $stmt->fetchAll(PDO::FETCH_ASSOC);

foreach ($articles as $article) {
    echo "{$article['title']}
"; } // Вывод ссылок на страницы for ($i = 1; $i <= $totalPages; $i++) { echo "$i "; }
Выводятся заголовки статей и ссылки страниц.
Пример: Статья 1 Статья 2 ... 1 2 3 ...

Пример 4: Обновление записи с проверкой существования

Пример

$id = 5;
$newEmail = 'new@example.com';

$stmt = $pdo->prepare('SELECT id FROM users WHERE id = :id');
$stmt->execute([':id' => $id]);
if (!$stmt->fetch()) {
    die('Пользователь не найден');
}

$updateStmt = $pdo->prepare('UPDATE users SET email = :email WHERE id = :id');
$updateStmt->execute([':email' => $newEmail, ':id' => $id]);
echo 'Email обновлён';
Email обновлён или Пользователь не найден

Пример 5: Удаление каскадом (с внешними ключами)

Пример

$userId = 10;
// Предполагается, что в таблице orders есть внешний ключ с ON DELETE CASCADE
$stmt = $pdo->prepare('DELETE FROM users WHERE id = :id');
$stmt->execute([':id' => $userId]);
echo 'Пользователь удалён вместе с заказами';
Пользователь удалён вместе с заказами
Если каскад не настроен: SQLSTATE[23000]: Integrity constraint violation...

Сайты на PHP и MySQL - comments

En
Php mysql сайты (php)