Kodokon kodokon.com

Формы: приём и валидация данных

Работай с формами как профессионал: правильный HTTP-метод, строгая проверка входных данных и безопасный повторный вывод.

9 мин · 3 вопросов

Открыть этот урок в Kodokon

Форма - это первая точка контакта между твоими пользователями и твоим PHP-кодом. Метод get помещает данные в URL (?q=pizza): идеально для поиска или фильтра, потому что страницу можно добавить в закладки и переслать. Метод post передаёт данные в теле запроса: это обязательный метод всякий раз, когда запрос что-то меняет (создание аккаунта, заказ, удаление) или несёт чувствительные данные. PHP складывает полученные значения в суперглобальные массивы $_GET и $_POST.

HTML
<form action="search.php" method="get">
  <label for="q">Search</label>
  <input id="q" name="q" type="text">
  <button type="submit">Search</button>
</form>
<?php
$query = trim($_GET['q'] ?? '');

if ($query !== '') {
    echo "<p>You are searching for: " .
        htmlspecialchars($query, ENT_QUOTES) . "</p>";
}
?>
search.php: форма и её обработка на одной странице.

Профессиональное правило номер один: никогда не доверяй входящим данным. Пользователь может отправить что угодно, включая подделанные значения, собранные вне твоей формы. Функция filter_input() читает и проверяет значение за один шаг: она возвращает проверенное значение, false - если оно некорректно, и null - если поле отсутствует; эти три случая стоит различать в сообщениях об ошибках.

PHP
<?php

declare(strict_types=1);

$errors = [];

$email = filter_input(
    INPUT_POST,
    'email',
    FILTER_VALIDATE_EMAIL
);

$age = filter_input(
    INPUT_POST,
    'age',
    FILTER_VALIDATE_INT,
    ['options' => ['min_range' => 18, 'max_range' => 120]]
);

$name = trim((string) ($_POST['name'] ?? ''));

if ($name === '' || mb_strlen($name) > 50) {
    $errors[] = "Name required (50 characters max).";
}

if (!is_string($email)) {
    $errors[] = "Invalid email address.";
}

if (!is_int($age)) {
    $errors[] = "Invalid age (between 18 and 120).";
}

if ($errors === []) {
    echo "Registration valid.";
}
Проверка регистрации с помощью filter_input().

Когда валидация не прошла, не отправляй обратно пустую форму: выведи заново значения, которые ввёл пользователь ("липкая" форма), и сообщения об ошибках рядом с нужными полями. Любое повторно выводимое значение должно пройти через htmlspecialchars(): именно она обезвреживает теги и не даёт внедрить скрипт.

HTML
<?php
$name = trim($_POST['name'] ?? '');
$hasError = isset($_POST['name']) && $name === '';
$safeName = htmlspecialchars($name, ENT_QUOTES);
?>
<form method="post" action="">
  <label for="name">Your name</label>
  <input id="name" name="name"
    value="<?= $safeName ?>">
  <?php if ($hasError): ?>
    <p>Name is required.</p>
  <?php endif; ?>
  <button type="submit">Submit</button>
</form>
Липкая форма: введённое значение переживает ошибку.

Проверка знаний

Убедись, что запомнил ключевые моменты этого урока.

  1. Какой HTTP-метод подходит для формы, которая создаёт аккаунт пользователя?
    • GET, чтобы данные оставались видны в URL
    • POST, потому что запрос меняет состояние сервера, а данные не должны попадать в URL
    • Подойдёт любой, это вопрос стиля
  2. Что вернёт filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL), если поле вообще не было отправлено?
    • false
    • Пустую строку
    • null
    • Будет выброшено исключение
  3. Зачем пропускать значение через htmlspecialchars() перед повторным выводом на странице?
    • Чтобы обезвредить HTML-теги и не дать внедрить скрипт (уязвимость XSS)
    • Чтобы автоматически исправить опечатки
    • Чтобы сжать значение и ускорить вывод