Урок 25

Удаление поста

25 мин

Особенности удаления

Удаление — опасная операция. Нужно:

  • Проверить права (только автор может удалить)
  • Попросить подтверждение
  • Использовать POST-запрос (не GET!)

Почему POST, а не GET?

Если удаление через GET (delete.php?id=5), то:

  • Браузер может сделать "prefetch" ссылки и случайно удалить пост
  • Злоумышленник может отправить вам ссылку, и при клике пост удалится

POST-запрос требует отправки формы, что безопаснее.

Страница удаления

Создайте файл public/delete_post.php:

<?php
require_once "includes/config.php";

// Только для авторизованных
requireLogin();

// Получаем ID поста
$id = isset($_GET["id"]) ? (int)$_GET["id"] : 0;

// Загружаем пост
$post = getPostById($id);

// Если пост не найден
if (!$post) {
    header("HTTP/1.0 404 Not Found");
    $page_title = "Пост не найден";
    include "includes/header.php";
    echo "<h2>Пост не найден</h2>";
    include "includes/footer.php";
    exit;
}

// Проверяем права
if (!isPostAuthor($post["user_id"])) {
    header("HTTP/1.0 403 Forbidden");
    $page_title = "Доступ запрещён";
    include "includes/header.php";
    echo "<h2>Вы не можете удалить чужой пост</h2>";
    include "includes/footer.php";
    exit;
}

// Обработка подтверждения удаления
if ($_SERVER["REQUEST_METHOD"] === "POST") {
    
    // Проверяем токен безопасности
    $token = $_POST["csrf_token"] ?? "";
    if ($token !== $_SESSION["csrf_token"]) {
        die("Недействительный токен безопасности");
    }
    
    // Удаляем пост
    $deleted = deletePost($id);
    
    if ($deleted) {
        // Устанавливаем сообщение об успехе
        $_SESSION["flash_message"] = "Пост успешно удалён";
        header("Location: index.php");
        exit;
    } else {
        $error = "Ошибка при удалении поста";
    }
}

// Генерируем CSRF-токен
$_SESSION["csrf_token"] = bin2hex(random_bytes(32));

$page_title = "Удалить пост — $site_name";
include "includes/header.php";
?>

<h2>Удаление поста</h2>

<div style="background: #fff3cd; border: 1px solid #ffc107; padding: 20px; border-radius: 8px; margin-bottom: 20px;">
    <strong>Внимание!</strong> Вы собираетесь удалить пост:
    <h3 style="margin: 15px 0 5px;"><?= escape($post["title"]) ?></h3>
    <p style="color: #666;">Это действие нельзя отменить.</p>
</div>

<form method="POST">
    <input type="hidden" name="csrf_token" value="<?= $_SESSION["csrf_token"] ?>">
    
    <button 
        type="submit"
        style="background: #dc3545; color: white; padding: 12px 30px; border: none; border-radius: 4px; font-size: 16px; cursor: pointer;"
    >
        Да, удалить
    </button>
    
    <a href="post.php?id=<?= $id ?>" style="margin-left: 15px; color: #666;">Отмена</a>
</form>

<?php include "includes/footer.php"; ?>

Что такое CSRF-токен?

CSRF (Cross-Site Request Forgery) — атака, когда злоумышленник заставляет ваш браузер выполнить действие от вашего имени.

CSRF-токен — случайная строка, которая:

  1. Генерируется при открытии формы
  2. Сохраняется в сессии
  3. Отправляется вместе с формой
  4. Проверяется при обработке

Злоумышленник не знает токен, поэтому не может подделать форму.

Flash-сообщения

Добавьте в includes/header.php после открытия <main>:

<?php if (isset($_SESSION["flash_message"])): ?>
    <div style="background: #d4edda; border: 1px solid #c3e6cb; padding: 15px; border-radius: 8px; margin-bottom: 20px;">
        <?= escape($_SESSION["flash_message"]) ?>
    </div>
    <?php unset($_SESSION["flash_message"]); ?>
<?php endif; ?>

"Flash-сообщение" показывается один раз и сразу удаляется.

Полный цикл управления постами

  1. Создайте пост
  2. Перейдите на страницу поста
  3. Нажмите "Редактировать" — измените текст — сохраните
  4. Нажмите "Удалить" — подтвердите
  5. На главной увидите "Пост успешно удалён"
Модуль 5 завершён!

Вы создали полноценный CRUD для постов:
✅ Create — создание
✅ Read — просмотр
✅ Update — редактирование
✅ Delete — удаление

В следующем модуле добавим админ-панель!

Мы используем файлы cookie для улучшения работы сайта и персонализации контента. Продолжая использовать сайт, вы соглашаетесь с использованием cookies в соответствии с нашей Политикой конфиденциальности.