Объединение фронтенда и бэкенда с помощью CSS, JavaScript, PHP и MySQL

Раздел: Веб-разработка -> Интеграция фронтенда и бэкенда

Основные подходы к интеграции

Как вывести данные из MySQL на страницу без использования JavaScript?

Цель: получить статическую HTML-страницу с данными из базы, подходящую для SEO и простых сайтов.


// index.php
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->query('SELECT name, price FROM products');
while ($row = $stmt->fetch()) {
    echo "<div class='product'><span class='fw-bold'>{$row['name']}</span> - {$row['price']} руб.</div>";
}
?>
  

Шаги: подключение к БД, выполнение запроса, вывод в HTML.

Ошибка: SQL инъекция - если запрос содержит пользовательский ввод. Решение: использовать подготовленные запросы (PDO). Также проблема: данные не обновляются без перезагрузки страницы.

Как асинхронно получать данные от PHP и обновлять DOM без перезагрузки?

Основное эффективное решение: fetch API + JSON. Цель: динамическое обновление контента, современные SPA-подходы.

Серверный файл (get_products.php):


<?php
header('Content-Type: application/json');
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->query('SELECT name, price FROM products');
$data = $stmt->fetchAll();
echo json_encode($data);
?>
  

Клиентский JavaScript:


fetch('get_products.php')
  .then(response => {
    if (!response.ok) throw new Error('Ошибка сети');
    return response.json();
  })
  .then(products => {
    const container = document.getElementById('products');
    container.innerHTML = products.map(p =>
      `<div class='product'><span class='fw-bold'>${p.name}</span> - ${p.price} руб.</div>`
    ).join('');
  })
  .catch(err => console.error('Проблема:', err));
  

Шаги: сервер возвращает JSON, клиент парсит и вставляет HTML.

Типичная ошибка: CORS при запросах на другой домен. Решение: настроить заголовки на сервере (Access-Control-Allow-Origin). Другая проблема: XSS при вставке непроверенных данных. Решение: экранировать вывод через textContent или санитизировать.

Как выполнять AJAX-запросы с помощью jQuery?

Цель: поддержка старых браузеров и упрощение кода в проектах, использующих jQuery.


$.getJSON('get_products.php', function(data) {
  var html = '';
  $.each(data, function(i, product) {
    html += '<div class="product"><span class="fw-bold">' + product.name + '</span> - ' + product.price + ' руб.</div>';
  });
  $('#products').html(html);
});
  

Проблема: jQuery добавляет дополнительный вес и может быть устаревшим. Ошибка: неправильный URL или отсутствие обработки ошибок. Решение: использовать catch с jQuery.fail().

Как отправить данные формы на сервер и сохранить в MySQL через AJAX?

Цель: обработка данных без перезагрузки страницы (например, лайки, комментарии).

PHP (save_comment.php):


<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->prepare('INSERT INTO comments (text, date) VALUES (?, NOW())');
$stmt->execute([$_POST['text']]);
echo json_encode(['status' => 'ok']);
?>
  

JavaScript (fetch с POST):


form.addEventListener('submit', function(e) {
  e.preventDefault();
  fetch('save_comment.php', {
    method: 'POST',
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    body: 'text=' + encodeURIComponent(textInput.value)
  }).then(r => r.json()).then(...);
});
  

Ошибка: SQL инъекция при использовании прямых подстановок. Решение: использовать prepared statements. Также CSRF - добавлять токен валидации.

Расширенные примеры интеграции

Ниже приведены подробные примеры с кодом и результатом, демонстрирующие нестандартные сценарии.

1. Динамическая фильтрация и сортировка через AJAX

Пример: каталог товаров с фильтром по категории и сортировкой по цене. PHP принимает GET-параметры, возвращает отфильтрованные данные в JSON.

Пример

// filter_products.php
<?php
$category = $_GET['category'] ?? '';
$sort = $_GET['sort'] ?? 'price_asc';
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$sql = 'SELECT name, price FROM products WHERE category = ? ORDER BY ' . ($sort === 'price_asc' ? 'price ASC' : 'price DESC');
$stmt = $pdo->prepare($sql);
$stmt->execute([$category]);
echo json_encode($stmt->fetchAll());
?>
Пример

// client.js
function loadProducts(category, sort) {
  const params = new URLSearchParams({category, sort});
  fetch('filter_products.php?' + params)
    .then(r => r.json())
    .then(products => {
      // обновление DOM
    });
}

Результат: в консоли браузера массив объектов с товарами. Ошибки: неверное имя столбца для сортировки может вызвать SQL-синтаксическую ошибку. Защита: проверять допустимые значения $sort в PHP.

2. Пагинация с использованием LIMIT и offset

Цель: загрузка данных страницами, уменьшая объем передаваемой информации.

Пример

// products_page.php?page=1&per_page=10
<?php
$page = (int)($_GET['page'] ?? 1);
$perPage = (int)($_GET['per_page'] ?? 10);
$offset = ($page - 1) * $perPage;
$stmt = $pdo->prepare('SELECT * FROM products LIMIT ? OFFSET ?');
$stmt->execute([$perPage, $offset]);
$products = $stmt->fetchAll();
// + получить общее количество для пагинации
$total = $pdo->query('SELECT COUNT(*) FROM products')->fetchColumn();
echo json_encode(['products' => $products, 'total' => $total, 'page' => $page]);
?>
Пример

// клиент: создание кнопок пагинации на основе total
fetch(`products_page.php?page=${currentPage}&per_page=10`)
  .then(r => r.json())
  .then(data => {
    // data.products - массив, data.total - всего записей
  });
{
  "products": [
    {"id":1,"name":"Товар 1","price":100},
    {"id":2,"name":"Товар 2","price":200}
  ],
  "total": 50,
  "page": 1
}

Проблема: большие значения OFFSET замедляют запрос на больших таблицах. Решение: использовать WHERE-фильтрацию по id (keyset pagination).

3. Защита от SQL-инъекций с помощью подготовленных запросов и экранирование вывода

Пример: безопасная вставка комментария.

Пример

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);
$stmt = $pdo->prepare('INSERT INTO comments (user_id, text) VALUES (?, ?)');
$stmt->execute([$userId, $text]);
// при выводе экранируем htmlspecialchars
?>
Пример

// client side
const safeText = document.createElement('div');
safeText.textContent = comment.text; // автоматическое экранирование
container.appendChild(safeText);

Результат: данные в БД безопасны, в DOM нет выполнения скриптов.

4. Загрузка файлов через FormData и AJAX

Цель: отправка изображения на сервер и сохранение ссылки в MySQL.

Пример

// upload.php
<?php
$targetDir = 'uploads/';
$fileName = basename($_FILES['file']['name']);
$targetFile = $targetDir . $fileName;
move_uploaded_file($_FILES['file']['tmp_name'], $targetFile);
// сохраняем путь в БД
$stmt = $pdo->prepare('INSERT INTO images (path) VALUES (?)');
$stmt->execute([$targetFile]);
echo json_encode(['path' => $targetFile]);
?>
Пример

// client
const formData = new FormData();
formData.append('file', fileInput.files[0]);
fetch('upload.php', {
  method: 'POST',
  body: formData
}).then(r => r.json()).then(data => {
  // data.path - URL загруженного файла
});
{"path":"uploads/photo.jpg"}

Проблема: безопасность - проверять тип и размер файла, запрещать исполняемые скрипты.

CSS JavaScript PHP MySQL - comments

En
Css javascript php mysql (php)