nmk

Лекція 12 (2 години). Реалізація CRUD: Читання та Створення

План лекції

  1. Поняття маніпулювання даними: акронім CRUD.
  2. Читання записів: оператор SELECT, метод $pdo->query() та fetchAll().
  3. Рендеринг списку: виведення даних з БД у HTML.
  4. Створення ресурсів: оператор INSERT та додавання нового запису.

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

Вступ

Ми навчилися підключатися до БД. Тепер настав час “оживити” наш сайт. Усі повноцінні веб-проєкти (чи то інтернет-магазин, чи блог, чи наш “Менеджер завдань”) базуються на чотирьох китах: ви можете Create (Створити) ресурс, Read (Прочитати) його, Update (Оновити) та Delete (Видалити) його. У цій лекції ми навчимося формувати SQL-запити через PHP для виконання перших двох літер: C (Створення) та R (Читання).


1. Що таке CRUD?

Майже кожен функціонал на сайті так чи інакше зводиться до CRUD:

2. Читання записів: оператор SELECT

Мова SQL створена так, щоб нагадувати звичайну англійську. Щоб прочитати інформацію, використовується команда SELECT (“обрати”).

Виконання через PDO: метод query()

Щоб виконати цей рядок за допомогою нашого “мосту” (змінної $pdo), ми використовуємо метод query(). Цей метод найкраще підходить для статичних, безпечних запитів, де ми просто кажемо базі “Дай усе” і не підмішуємо жодного вводу від користувача (такого як пошукові фрази).

<?php
require_once 'db.php'; // Інтегрували підключення (отримали об'єкт $pdo)

// 1. Формуємо рядок SQL-запиту
$sql = 'SELECT * FROM tasks ORDER BY id DESC'; // ORDER BY DESC - найсвіжіші зверху

// 2. Відправляємо запит до БД
$stmt = $pdo->query($sql);

// $stmt (Statement) - це ще НЕ масив рядків. Це об'єкт "результату",
// який тримає в собі відповідь сервера бази даних.
?>

Вилучення масиву: fetchAll()

Щоб перетворити технічний $stmt на звичайний PHP-масив, ми викликаємо метод fetchAll(). Завжди передавайте йому параметр конфігурації PDO::FETCH_ASSOC, щоб повернути чистий асоціативний масив за ключами колонок і зекономити оперативну пам’ять сервера:

<?php
// 3. Завантажуємо всі рядки у змінну $tasks
$tasks = $stmt->fetchAll(PDO::FETCH_ASSOC);

/* Тепер $tasks це звичний багатовимірний масив:
[
  [ "id" => "2", "title" => "Зробити ДЗ", "status" => "0" ],
  [ "id" => "1", "title" => "Купити Хліб", "status" => "1" ]
]
*/
?>

3. Рендеринг списку: виведення у HTML

Тепер, коли ми маємо PHP-масив у змінній $tasks, нам потрібно його лише перебрати стандартним циклом foreach всередині нашого HTML-шаблону index.php. Важливо: щоб хакер не зміг заразити наш сайт через введені раніше JavaScript-теги у базу, будь-який вивід текстових даних з БД має “очищуватися” функцією htmlspecialchars().

<!DOCTYPE html>
<html>
  <body>
    <h1>Список усіх завдань</h1>
    <ul>
      <?php foreach ($tasks as $task): ?>
      <li>
        <strong><?= htmlspecialchars($task['title']) ?></strong>
        <small>(Статус: <?= $task['status'] ?>)</small>
      </li>
      <?php endforeach; ?>
    </ul>
  </body>
</html>

4. Створення ресурсів: оператор INSERT

Тепер реалізуємо можливість додати нове завдання (літера C - Create). За це в SQL відповідає оператор INSERT INTO. Синтаксис: INSERT INTO таблиця (стовпець1, стовпець2) VALUES ('значення1', 'значення2'). Зверніть увагу: ми ніколи не вставляємо стовпець id, тому що він має прапорець Auto_Increment у нашій базі та створюється автоматично.

Уявімо скрипт add_task.php, який приймає Дані з POST-форми:

<?php
require_once 'db.php';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $newTaskTitle = $_POST['title']; // 'Прибрати в кімнаті'

    // БАЗОВИЙ ПРИКЛАД: ми "вклеюємо" змінну прямісінько в рядок запиту.
    // УВАГА! Цей метод ($pdo->query з конкатенацією) є вкрай небезпечним
    // для справжніх проєктів (через SQL-ін'єкції!). Ми використаємо його тут
    // виключно для початкового розуміння логіки роботи SQL. На Лекції 14
    // ми зробимо цей код безпечним і професійним!

    $sql = "INSERT INTO tasks (title, status) VALUES ('$newTaskTitle', 0)";

    // Відправляємо сформований текст до MySQL
    $pdo->query($sql);

    // Перенаправляємо (Redirect) назад на головну сторінку, щоб уникнути
    // повторної відправки форми, якщо юзер натисне F5 (Оновлення сторінки)
    header("Location: index.php");
    exit;
}
?>

Створивши HTML форму введення і направивши її action="add_task.php" method="POST", ви тепер маєте повноцінний цикл створення та прочитання (Create + Read).


Висновки

  1. Поняття CRUD визначає фундаментальну логіку маніпулювання даними в будь-якому вебсайті (Створення, Читання, Оновлення, Видалення).
  2. Запит SELECT виконується методом $pdo->query() і повертає об’єкт-стейтмент, масив з якого витягується через fetchAll(PDO::FETCH_ASSOC).
  3. Виведення багатовимірних масивів у клієнтський інтерфейс найефективніше здійснювати за допомогою циклу foreach всередині HTML.
  4. Додавання нового рядку відбувається через SQL-команду INSERT INTO. Стовпці з властивістю Auto_Increment вписувати під час вставки не потрібно.
  5. Завжди завершуйте скрипт додавання (POST-обробник) інструкцією header('Location: ...'), для повернення на сторінку-список та захисту від дублювання дії.

Джерела

  1. Синтаксис SELECT: https://www.w3schools.com/sql/sql_select.asp
  2. Синтаксис INSERT: https://www.w3schools.com/sql/sql_insert.asp
  3. Метод fetchAll: https://www.php.net/manual/ru/pdostatement.fetchall.php

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

  1. Розшифруйте і поясніть кожну з чотирьох літер загальноприйнятого акроніму CRUD. З якими основними SQL-операторами ці літери співвідносяться?
  2. Опишіть, у якому вигляді метод $stmt->fetchAll(PDO::FETCH_ASSOC) віддає нам дані з таблиці. Чому використання прапорця FETCH_ASSOC є кращою практикою, аніж його відсутність?
  3. Чому архітектурно правильно не виводити SQL-запити прямо посеред <ul> списку, а робити $pdo->query в самому верху PHP-файлу (чи в окремому контролері), і лише нижче в HTML ітерувати його через foreach?
  4. Під час складання запиту INSERT INTO users (name, email) VALUES ... ми пропустили стовпець id. Чому база не видасть помилки і звідки вона знатиме, який ID присвоїти новоствореному користувачу?
  5. Згадайте інструкцію header("Location: index.php"); exit;. Що станеться, якщо після додавання товару в кошик через POST, система просто “намалює” сторінку-успіх без редиректа, а користувач випадково натисне F5 (Refresh) у своєму браузері?