🔐 ЗАЩИТА:
- ip_check.php — фильтр по IP
- session_start() + проверка $_SESSION['user']
- CSRF-токен — защита от подделки запросов
- htmlspecialchars() — защита от XSS везде
- PDO + подготовленные запросы — защита от SQL-инъекций
- (int) для category_id — приведение к числу
- trim() — очистка от пробелов
📝 ВАЛИДАЦИЯ:
- Заголовок — обязателен
- Текст статьи — обязателен
- Вывод ошибок и сообщений об успехе
🗂️ БАЗА ДАННЫХ:
- SELECT categories — получение списка категорий
- INSERT INTO articles — сохранение статьи
- lastInsertId() — ID новой статьи
⚙️ ФУНКЦИИ ФОРМЫ:
- Meta Title / Description — для SEO
- Теги (через запятую) — автодополнение
- Изображение — ручной ввод + файловый браузер
- Краткое описание — preview_text
- Категория — выпадающий список
- Предпросмотр — безопасный показ содержимого
- Редирект через 2 секунды после сохранения
📦 ПОДКЛЮЧЕНИЯ:
- ../includes/header.php
- ../includes/admin_menu.php
- ../includes/footer.php
- ../includes/db.php
- tag-autocomplete.js — автодополнение тегов
- jQuery + jQuery UI
<?php
include('ip_check.php');
session_start();
if (!isset($_SESSION['user'])) {
header("Location: login.php");
exit;
}
include '../includes/header.php';
require '../includes/db.php';
// CSRF-токен
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
$error = '';
$success = '';
$form_data = [
'title' => '',
'preview_text' => '',
'content' => '',
'image' => '',
'meta_title' => '',
'meta_description' => '',
'category_id' => ''
];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Проверка CSRF
if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
die("CSRF атака!");
}
// Получаем данные
$form_data['title'] = trim($_POST['title'] ?? '');
$form_data['content'] = $_POST['content'] ?? '';
$form_data['preview_text'] = trim($_POST['preview_text'] ?? '');
$form_data['image'] = trim($_POST['image'] ?? '');
$form_data['meta_title'] = trim($_POST['meta_title'] ?? '');
$form_data['meta_description'] = trim($_POST['meta_description'] ?? '');
$form_data['category_id'] = !empty($_POST['category_id']) ? (int)$_POST['category_id'] : null;
// Валидация
if (empty($form_data['title'])) {
$error = "❌ Заголовок обязателен!";
} elseif (empty($form_data['content'])) {
$error = "❌ Текст статьи обязателен!";
} else {
// Сохраняем в БД
$stmt = $pdo->prepare("INSERT INTO articles
(title, content, preview_text, image, category_id, meta_title, meta_description, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, NOW())");
$stmt->execute([
$form_data['title'],
$form_data['content'],
$form_data['preview_text'],
$form_data['image'],
$form_data['category_id'],
$form_data['meta_title'],
$form_data['meta_description']
]);
$success = "✅ Статья успешно добавлена!";
// Очищаем форму
$form_data = [
'title' => '',
'preview_text' => '',
'content' => '',
'image' => '',
'meta_title' => '',
'meta_description' => '',
'category_id' => ''
];
// Редирект через 2 секунды
header("refresh:2;url=index.php");
}
}
// Получаем список категорий
$categories = $pdo->query("SELECT id, name FROM categories ORDER BY name")->fetchAll();
?>
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Добавить статью — Админка</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/css/adminka.css">
<script src="tag-autocomplete.js"></script>
<style>
.error { background: #f44336; color: white; padding: 10px; border-radius: 5px; margin: 10px 0; }
.success { background: #4CAF50; color: white; padding: 10px; border-radius: 5px; margin: 10px 0; }
.preview { border: 1px solid #ccc; padding: 1em; background: #f9f9f9; margin: 10px 0; max-height: 300px; overflow: auto; }
.form-group { margin-bottom: 15px; }
.form-group label { display: block; font-weight: bold; margin-bottom: 5px; }
.form-group input, .form-group textarea, .form-group select { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; }
button, input[type="submit"] { background: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }
button:hover, input[type="submit"]:hover { background: #0056b3; }
</style>
</head>
<body>
<div class="container">
<?php include '../includes/admin_menu.php'; ?>
<h2>📝 Добавить статью</h2>
<?php if ($error): ?>
<div class="error"><?= htmlspecialchars($error) ?></div>
<?php endif; ?>
<?php if ($success): ?>
<div class="success"><?= htmlspecialchars($success) ?></div>
<?php endif; ?>
<form method="post">
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
<div class="form-group">
<label>🏷️ Теги (через запятую)</label>
<input type="text" id="tag-input" name="tags" placeholder="Начните вводить тег...">
</div>
<div class="form-group">
<label>📝 Meta Title (SEO)</label>
<input type="text" name="meta_title" value="<?= htmlspecialchars($form_data['meta_title']) ?>">
</div>
<div class="form-group">
<label>📄 Meta Description (SEO)</label>
<textarea name="meta_description" rows="3"><?= htmlspecialchars($form_data['meta_description']) ?></textarea>
</div>
<div class="form-group">
<label>📌 Заголовок *</label>
<input type="text" name="title" required value="<?= htmlspecialchars($form_data['title']) ?>">
</div>
<div class="form-group">
<label>📷 Изображение</label>
<div style="display: flex; gap: 10px;">
<input type="text" name="image" value="<?= htmlspecialchars($form_data['image']) ?>" style="flex:1">
<button type="button" onclick="window.open('file_browser.php', 'FileBrowser', 'width=600,height=400')">📁 Выбрать</button>
</div>
</div>
<div class="form-group">
<label>📖 Краткое описание (предпросмотр)</label>
<textarea name="preview_text" rows="4"><?= htmlspecialchars($form_data['preview_text']) ?></textarea>
</div>
<div class="form-group">
<label>📚 Категория</label>
<select name="category_id">
<option value="">— Без категории —</option>
<?php foreach ($categories as $cat): ?>
<option value="<?= $cat['id'] ?>" <?= $form_data['category_id'] == $cat['id'] ? 'selected' : '' ?>>
<?= htmlspecialchars($cat['name']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label>📄 Текст статьи *</label>
<textarea name="content" rows="20"><?= htmlspecialchars($form_data['content']) ?></textarea>
</div>
<?php if (!empty($form_data['content'])): ?>
<h3>👁️ Предпросмотр (только для админа)</h3>
<div class="preview">
<?= nl2br(htmlspecialchars($form_data['content'])) ?>
</div>
<?php endif; ?>
<input type="submit" value="💾 Сохранить статью">
</form>
<?php include '../includes/footer.php'; ?>
</div>
</body>
</html>
Комментарии
Пока нет комментариев. Будьте первым!