nmk

Лекція 13 (2 години). Реалізація CRUD: Оновлення та Видалення

План лекції

  1. Небезпека масових операцій без умови WHERE.
  2. Робота з ідентифікаторами (ID): унікалізація кожного запису.
  3. Видалення записів: оператор DELETE та передача ID через $_GET.
  4. Оновлення записів: оператор UPDATE та збереження змін із форми.

Перелік умовних скорочень

Вступ

Ми навчилися створювати та виводити завдання у нашому проєкті. Але життєвий цикл інформації на цьому не завершується. Користувачу обов’язково треба дозволити редагувати власні записи (можливо він помилився) та безповоротно видаляти їх, якщо вони більше не актуальні. Ці дві операції з абревіатури CRUD (Update та Delete) вважаються технічно найбільш небезпечними. У цій лекції ми навчимось грамотно керувати зміною статусу та знищенням об’єктів за їхнім унікальним Ідентифікатором (id).


1. Небезпека масових операцій без WHERE

Оператори UPDATE та DELETE за замовчуванням діють на ВСЮ ТАБЛИЦЮ ОДРАЗУ. Якщо ви забудете вказати системі, до якого конкретного запису треба застосувати зміни, станеться катастрофа:

DELETE FROM tasks; — Цей запит без попереджень видалить або очистить всю таблицю завдань за частку секунди. UPDATE tasks SET status = 'виконано'; — Цей запит зробить “виконаними” абсолютно всі завдання у системі.

Щоб цього уникнути, завжди додається конструкція фільтрації WHERE (Де).

DELETE FROM tasks WHERE id = 5; — Видалить безпечно тільки одне завдання з номером 5.

2. Робота з ідентифікаторами (ID)

А як наш PHP-скрипт дізнається, що користувач хоче видалити саме завдання №5? Найпоширеніша практика — генерувати спеціальні кнопки (або посилання) прямо під час 12 лекції в циклі foreach. До кожного посилання ми динамічно “підклеюємо” ID завдання у рядок запиту (передача через метод GET).

Клієнтська сторона (Генеруємо посилання в index.php)

<ul>
  <?php foreach ($tasks as $t): ?>
  <li>
    <?= htmlspecialchars($t['title']) ?>

    <!-- Формуємо GET-параметр. Наприклад вийде href="delete.php?id=5" -->
    <a href="delete.php?id=<?= $t['id'] ?>" style="color:red;">❌ Видалити</a>

    <!-- А тут посилання для виконання -->
    <a href="complete.php?id=<?= $t['id'] ?>" style="color:green;"
      >✅ Зробити</a
    >
  </li>
  <?php endforeach; ?>
</ul>

3. Видалення записів: оператор DELETE

Видалення є найпростішою операцією в SQL, оскільки ми передаємо тільки сам ID. Створимо файл delete.php, на який веде наше посилання. Він перехопить цей ID з суперглобального масиву $_GET.

<?php
require_once 'db.php';

// Перевіряємо, чи є id в адресі до того, як продовжити
if (isset($_GET['id'])) {

    // ДО УВАГИ: використання '$id' прямо в рядку - це НЕБЕЗПЕЧНА тимчасова
    // практика. Ми не робимо жодної перевірки "А раптом id = 5 OR 1=1"?
    // Про правильний підхід (Prepared Statements) - на наступній лекції.
    $id = $_GET['id'];

    $sql = "DELETE FROM tasks WHERE id = $id";
    $pdo->query($sql);

    // Redirect на головну після видалення
    header("Location: index.php");
    exit;
} else {
    echo "Помилка: Не передано ідентифікатор завдання!";
}
?>

4. Оновлення записів: оператор UPDATE

Операція редагування дещо складніша, оскільки вона вимагає вказати: “яку таблицю оновити”, “ЯКІ поля змінити (SET)” і “для якого запису (WHERE)”.

Синтаксис: UPDATE таблиця SET колонка1 = 'нове значення', колонка2 = 1 WHERE id = X

Приклад 1: Зміна статусу (в один клік)

Сценарій обробника complete.php (коли ми натиснули на “Зробити”):

<?php
require_once 'db.php';

if (isset($_GET['id'])) {
    $id = $_GET['id'];
    // Ми НЕ чіпаємо 'title', ми оновлюємо ЛИШЕ колонку 'status'!
    $sql = "UPDATE tasks SET status = 1 WHERE id = $id";
    $pdo->query($sql);

    header('Location: index.php');
    exit;
}
?>

Приклад 2: Повноцінна форма редагування тексту завдання

Якщо ми хочемо дати користувачу змогу переписати текст завдання, процес розтягується на 2 сторінки:

  1. Ви робите сторінку edit.php?id=5.
  2. На цій сторінці робите SELECT * FROM tasks WHERE id = 5 щоб витягнути старий текст з бази.
  3. Малюєте <form method="POST"> і вставляєте цей старий текст прямо в <input value="<?= $old['title'] ?>">.
  4. Коли користувач тисне Submit (POST-запит), ви приймаєте змінений текст і робите: UPDATE tasks SET title = '$newText' WHERE id = 5.

Висновки

  1. Оператори зміни даних UPDATE і DELETE є фатально руйнівними, якщо застосовуються без ключового слова фільтрації WHERE. Завжди обмежуйте сферу їхньої дії ідентифікаторами (id) конкретних рядків.
  2. Процедура ідентифікації об’єктів для CRUD (Зміна, Видалення) зазвичай реалізується через метод GET — шляхом підклеювання параметрів до посилань href="module.php?id=.... Аналіз і вилучення цих значень на сервері відбувається через суперглобальний масив $_GET.
  3. Для видалення використовується скорочений оператор DELETE FROM table WHERE id=X. Для оновлення розширений — UPDATE table SET key=value WHERE id=X.
  4. Звичка завершувати будь-які обробники (delete.php чи complete.php) інструкцією HTTP Redirect-у (header('Location: ...')) дозволяє повернути користувача назад без відображення технічної порожнечі обробника та відвернути дублювання пост-запитів.
  5. Закидання сирих змінних із $_GET прямо в текст SQL-запиту є тимчасовим рішенням (Вразливістю). Наступною фундаментальною сходинкою розробника є опанування Підготовлених Запитів для 100% безпеки таких операцій (SQL Injections).

Джерела

  1. Синтаксис UPDATE: https://www.w3schools.com/sql/sql_update.asp
  2. Синтаксис DELETE: https://www.w3schools.com/sql/sql_delete.asp

Запитання для самоперевірки

  1. Згадайте небезпеку DELETE FROM users. Якого базового і життєво необхідного слова бракує в цьому запиті, і до яких катастрофічних наслідків призведе його виконання “в лоб” на реальній працюючій системі?
  2. Яким стандартним способом у парадигмі класичної PHP-маршрутизації ми змушуємо скрипт delete.php дізнатись, який саме ID товару хоче видалити користувач, якщо він просто клікає на кнопку <a href=""> без використання форм? Що змінюється в адресному рядку?
  3. В чому полягає різниця між зміною статусу завдання через кнопку “Виконано” та повноцінною зміною заголовка цього завдання? Скільки SQL запитів та проміжних сторінок знадобиться для другого сценарію (форми редагування)?
  4. Назвіть SQL Запит типу UPDATE для таблиці products, з метою зміни виключно поля “price” (ціни) на цифру 25 і тільки для того товару, що має “id” = 89. (Напишіть сам рядок запиту).
  5. Чому наприкінці файлу delete.php (там де ми видалили товар) ми майже завжди змушені прописувати внутрішню функцію header("Location: index.php");? Що саме побачить клієнт браузером і де він “зависне”, якщо ми пропустимо цю команду, але запит до бази спрацює коректно?