nmk

Лекція 7 (2 години). Робота з HTML-формами

План лекції

  1. Аналіз архітектури HTML-форми (method, action, name).
  2. Отримання даних на сервері через суперглобальний масив $_POST.
  3. Базова валідація даних (на пустоту, довжину, зміну типів).
  4. Збереження стану відповідей користувача (Sticky Forms).

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

Вступ

Форми — це єдине легальне “вікно” між кінцевим користувачем Вашого сайту і вашим PHP-сервером. Через форми користувачі автентифікуються, публікують дописи, завантажують файли та здійснюють оплати. Проте, потрібно завжди жити за правилом “Ніколи не довіряйте користувацькому введенню (Never trust user input)”. У цій лекції ми навчимось грамотно “ловити” відправлені анкети в PHP, обробляти масив $_POST і будувати фундамент для валідації (перевірки) введених даних ще до того, як вони потраплять до Бази Даних, що є ключем до інформаційної безпеки проєкту.


1. Аналіз архітектури HTML-форми

Перш ніж PHP отримає дані, браузер мусить їх коректно упакувати і відправити. За це відповідає тег-контейнер <form>.

Він має два критично важливі атрибути:

Для кожного поля вводу всередині форми обов’язковим є атрибут name. Без нього браузер не прикріпить “вміст” до відправки (він буде ігноруватися). Атрибут id використовується для CSS/JavaScript, PHP його повністю ігнорує.

<!-- Форма відправляє дані методом POST на обробник login.php -->
<form action="login.php" method="POST">
  <label>Електронна Пошта:</label>
  <!-- name="user_email" — це КЛЮЧ майбутнього масиву в PHP -->
  <input type="email" name="user_email" required />

  <label>Пароль:</label>
  <input type="password" name="user_pass" />

  <button type="submit">Увійти</button>
</form>

2. Отримання даних через суперглобальний масив $_POST

Після натискання користувачем кнопки submit, браузер робить HTTP POST запит. Інтерпретатор PHP на сервері перехоплює тіло запиту та розкладає його на пари “Ключ-Значення” у суперглобальний масив $_POST.

У файлі-обробнику login.php:

<?php
// Перевіряємо, чи був цей файл взагалі запущений натисканням форми,
// чи хтось просто написав адресу "login.php" у барузері?
if ($_SERVER['REQUEST_METHOD'] === 'POST') {

    // Щоб подивитися всі наявні дані (для розробників):
    var_dump($_POST);

    // Дістаємо конкретні поля за їхніми `name`
    $email = $_POST['user_email'] ?? '';
    $pass  = $_POST['user_pass']  ?? '';

    echo "Ви намагаєтеся ввійти з поштою: " . $email;
} else {
    echo "Помилка. Доступ дозволено лише для POST-запитів.";
}
?>

Застосування оператора об’єднання ?? '' необхідне для уникнення помилок (Warnings) у випадку, коли поле з таким іменем не було надіслано.

3. Базова валідація та санація

Валідація буває клієнтською (браузерною, через HTML5 атрибути типу required, minlength або JS) і серверною (PHP). Серверна валідація єдина забезпечує надійність, адже будь-який досвідчений школяр через DevTools (кнопку F12) здатний видалити атрибут required з вашої HTML-форми та надіслати порожнє значення в систему!

Санація (Очищення даних перед перевіркою)

Користувачі часто (чи випадково) роблять помилки: ставлять випадковий пробіл у кінці логіна і не можуть ввійти. Сервер повинен почистити це trim($string), яка обрізає пробіли до і після тексту. А задля уникнення Хакерських атак типу XSS (Міжсайтовий скриптинг), де замість імені вставляють скрипт <script>alert(...), нам треба застосувати htmlspecialchars().

// ПРОФЕСІЙНИЙ підхід отримання даних:
$cleanEmail = htmlspecialchars( trim($_POST['user_email']) );

Складання масиву помилок (Error Bag)

Поганою практикою є використання команди die() під час першої знайденої помилки, адже ми не скажемо що іще користувач ввів не так. Правильно збирати помилки в один масив $errors.

<?php
$errors = [];

// Валідація на пустоту
if (empty($cleanEmail)) { // empty() - перевіряє що рядок порожній ("")
    $errors[] = 'Поле "Електронна Пошта" порожнє!';
}

// Перевірка на "Довжину пароля" (більше 6 букв)
if (strlen($_POST['user_pass']) < 6) {
    $errors[] = 'Пароль занадто короткий. Мінімум 6 символів.';
}

// Результат:
if (!empty($errors)) {
    // В масиві є рядки. Значить були помилки.
    foreach($errors as $errorMsg) {
        echo "<p style='color:red'>$errorMsg</p>";
    }
} else {
    // Масив порожній. Всі валідації пройшли УСПІШНО!
    echo "<p style='color:green'>Введено ідеально! Зберігаємо...</p>";
}
?>

4. Збереження стану відповідей користувача (Sticky Forms)

Проблема: Уявіть, що ви заповнили гігантську форму реєстрації на 15 полів. У самому кінці “забули” поставити галочку “Згоден з правилами”. Ви натискає “Відправити”. PHP відкидає запит, видає помилку і перевантажує сторінку… І всі ваші 15 уведених полів безслідно зникли, стали порожніми (відповідно до HTTP Stateless). Як користувач, ви більше сюди не повернетесь.

Рішення (Sticky Forms “Липкі форми”): PHP-сервер, якщо знаходить помилку, не просто перезавантажує сторінку чистокровно. Він перевіряє: якщо в $_POST уже було щось (наприклад, ім’я), він автоматично вставляє це в атрибут HTML value="", щоб поле не обнулялося до дефолтних.

<?php
// Ініціалізація змінної (можливим значенням з попереднього POST-запиту)
$oldEmail = $_POST['user_email'] ?? ''; 
?>

<!-- Імплементуємо Sticky Form: Вбудовуємо $oldEmail у параметр value -->
<input
  type="email"
  name="user_email"
  value="<?= htmlspecialchars($oldEmail) ?>"
/>

Використовуючи форму таким способом, після невдалої валідації форма знову перезавантажиться з червоним текстом помилки, але в полі Email уже залишиться (збережеться) усе, що було введене хвилину тому.


Висновки

  1. HTML-форми — інструмент пересилання користувацьких даних на сервер через метод POST (як правило). Атрибут name відповідає за іменування ключів майбутнього масиву для PHP.
  2. Серверна валідація даних у PHP є 100% обов’язковою незалежно від того, як сильно ви “обгорнули” форму обов’язковостями у фронтенд-коді. Хакери можуть надсилати POST-запити до вашого action.php, взагалі навіть не відкриваючи сторінку з HTML-формою.
  3. Процес обробки включає Санацію даних (trim, htmlspecialchars), та Перевірку (на пустоту empty, на типи даних і мінімальні розміри рядка strlen).
  4. Якісні веб-сайти використовують паттерн Sticky Forms, щоб значення атрибута value="" рендерилось на PHP і зберігало поточне введення користувача в разі появи помилки в сусідніх полях.

Джерела

  1. Форми (Офіційний Docs MDN): https://developer.mozilla.org/ru/docs/Learn_web_development/Core/Forms/Sending_and_retrieving_form_data
  2. PHP Variables From External Sources: https://www.php.net/manual/en/language.variables.external.php

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

  1. Знайдіть помилку в логіці: “Ми додали атрибут required для поля email і вказали type=email. Це означає, що можемо безпечно й відразу зберігати змінну $_POST['user'] в базі даних”. Поясніть концепцію Клієнтської і Серверної валідацій.
  2. Яким виявиться вміст масиву $_POST всередині PHP, якщо HTML-форма містить елемент <input id="super_login" class="login-field" type="text" /> (але користувач ввів туди “Admin”)? Чому?
  3. Що таке і для якого класу вразливостей застосовують функцію htmlspecialchars()? Що станеться, якщо нею не обгорнути коментар з текстом <script>alert('Hello!')</script>, який написав хакер?
  4. Розроблений вами сайт має дуже велику форму опитування (5 текстових полів, 3 радіокнопки тощо). Розкажіть теоретично концепцію (Як впровадити алгоритм), щоб у разі помилки Валідації користувачу не довелось вводити все наново (Sticky Forms).
  5. Яку перевірку в $_SERVER необхідно реалізувати В САМОМУ ПОЧАТКУ скрипта, який приймає форму, щоб гарантувати, що він спрацює ТІЛЬКИ на події “Submit” з форми, а не на прямому відкритті URL у браузері через Enter?