Объединение фронтенда и бэкенда с помощью 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"}
Проблема: безопасность - проверять тип и размер файла, запрещать исполняемые скрипты.