PHP · walidacja danych

Walidacja danych w PHP — sprawdzanie informacji z formularza

trim, mb_strlen, filter_var, in_array i lista błędów według pól. Trzy zadania na danych testowych i typowe pułapki.

45 minutPoziom podstawowyPliki i rozwiązania

Materiał redakcyjny TablicaPro · liceum i technikum

<?php
var_dump(filter_var("abc", FILTER_VALIDATE_INT));
bool(false)
Wiek "abc" odrzucony.

Dane z formularza zawsze trzeba sprawdzić na serwerze — przeglądarkę można ominąć, a pole „wiek” może dojść jako tekst abc, pusty napis albo liczba z kosmosu. Walidacja w PHP polega na sprawdzeniu każdego pola według reguł i zebraniu komunikatów o błędach, które zostaną pokazane użytkownikowi. Na lekcji uczniowie piszą funkcję waliduj i testują ją na zestawach danych.

Scenariusz jest przeznaczony na 45 minut dla klasy znającej tablice i funkcje w PHP oraz formularze — na przykład po lekcji o formularzach PHP i lekcji o funkcjach.

Przygotowanie stanowisk

Potrzebny jest PHP 8.x uruchamiany w terminalu (na przykład z pakietu XAMPP; sprawdź polecenie php -v). Rozpakuj pakiet z sekcji materiałów do osobnego folderu i przejdź do niego w terminalu. Skrypty uruchamiasz poleceniem php start.php; serwer WWW nie jest potrzebny, a wynik pojawia się w terminalu. Jeśli pobierasz pojedyncze pliki .php.txt ze strony zamiast ZIP, usuń końcówkę .txt lokalnie.

Cele i plan lekcji

Po zajęciach uczeń potrafi:

  • sprawdzić długość tekstu po usunięciu spacji (trim, mb_strlen);
  • sprawdzić adres e-mail i liczbę całkowitą z zakresem funkcją filter_var;
  • sprawdzić, czy wartość należy do listy dozwolonych (in_array w trybie ścisłym);
  • zebrać błędy w tablicy według nazw pól i wypisać je bezpiecznie.
CzasPraca na lekcji
0–5 minProblem: dane, którym nie można ufać
5–15 mintrim, mb_strlen, filter_var
15–22 minLista błędów według pól
22–37 minTrzy zadania samodzielne
37–42 minPrzypadki brzegowe
42–45 minPytania kontrolne

Reguły walidacji

Dane z formularza trafiają do PHP jako teksty ($_POST, $_GET), a pola mogą w ogóle nie dojść — dlatego każdy odczyt zabezpieczamy operatorem ??. Funkcja waliduj(array $dane): array zwraca tablicę błędów, w której kluczem jest nazwa pola; pusta tablica oznacza dane poprawne.

  • Tekst: trim usuwa spacje z początku i końca, a mb_strlen liczy znaki (zwykłe strlen liczy bajty, więc polskie litery liczyłby podwójnie).
  • E-mail: filter_var($email, FILTER_VALIDATE_EMAIL) zwraca adres lub false. Sprawdza format, a nie istnienie adresu.
  • Liczba całkowita: filter_var($wiek, FILTER_VALIDATE_INT, ["options" => ["min_range" => 10, "max_range" => 99]]) zwraca liczbę lub false; odrzuca ułamki ("16.5"), litery i pusty tekst. Uwaga: poprawne 0 też jest wartością „fałszywą”, dlatego wynik porównujemy z false ściśle (=== false).
  • Lista dozwolonych wartości: in_array($klasa, ["1", "2", "3", "4"], true) — ostatni argument włącza porównanie ścisłe.

Komunikaty wypisujemy z htmlspecialchars, bo mogą zawierać dane użytkownika. Walidacja po stronie serwera jest obowiązkowa; atrybuty required i pattern w HTML tylko ułatwiają pracę użytkownikowi.

Zadania

Zadanie 1. Poprawne dane. Napisz waliduj(array $dane): array sprawdzającą pola imie (co najmniej 2 znaki po trim), email, wiek (10–99) i klasa (1–4). Sprawdź dane ["imie" => "Ola", "email" => "ola@example.com", "wiek" => "16", "klasa" => "2"] — liczba błędów ma wynosić 0.

Zadanie 2. Błędne dane. Sprawdź ["imie" => " O ", "email" => "ola@", "wiek" => "9", "klasa" => "7"] i wypisz komunikat dla każdego pola.

Zadanie 3. Brakujące pola i wiek. Wypisz nazwy pól z błędami dla danych zawierających tylko imię. Sprawdź filter_var z zakresem dla wartości "16", "9", "100", "16.5", "abc" i pustego tekstu oraz wypisz znaczniki HTML bezpiecznie.

Dla chętnych: sprawdź funkcją filter_var adresy a@b.pl, a@b, @b.pl i a b@c.pl.

Rozwiązanie i wyniki

<?php
function waliduj(array $dane): array
{
    $bledy = [];
    $imie = trim((string) ($dane["imie"] ?? ""));
    if (mb_strlen($imie) < 2) {
        $bledy["imie"] = "Imie musi miec co najmniej 2 znaki.";
    }
    $email = trim((string) ($dane["email"] ?? ""));
    if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
        $bledy["email"] = "Podaj poprawny adres e-mail.";
    }
    $wiek = filter_var($dane["wiek"] ?? "", FILTER_VALIDATE_INT, ["options" => ["min_range" => 10, "max_range" => 99]]);
    if ($wiek === false) {
        $bledy["wiek"] = "Wiek to liczba od 10 do 99.";
    }
    if (!in_array($dane["klasa"] ?? "", ["1", "2", "3", "4"], true)) {
        $bledy["klasa"] = "Wybierz klase od 1 do 4.";
    }
    return $bledy;
}

// Zadanie 1
$poprawne = ["imie" => "Ola", "email" => "ola@example.com", "wiek" => "16", "klasa" => "2"];
echo count(waliduj($poprawne)), "\n";

// Zadanie 2
$bledne = ["imie" => " O ", "email" => "ola@", "wiek" => "9", "klasa" => "7"];
foreach (waliduj($bledne) as $pole => $komunikat) {
    echo $pole, ": ", $komunikat, "\n";
}

// Zadanie 3
echo implode(",", array_keys(waliduj(["imie" => "Jan"]))), "\n";
foreach (["16", "9", "100", "16.5", "abc", ""] as $wiek) {
    $ok = filter_var($wiek, FILTER_VALIDATE_INT, ["options" => ["min_range" => 10, "max_range" => 99]]);
    echo var_export($wiek, true), " ", $ok === false ? "zly" : "ok", "\n";
}
echo htmlspecialchars("<b>zle</b>", ENT_QUOTES, "UTF-8"), "\n";

Program wypisze:

0
imie: Imie musi miec co najmniej 2 znaki.
email: Podaj poprawny adres e-mail.
wiek: Wiek to liczba od 10 do 99.
klasa: Wybierz klase od 1 do 4.
email,wiek,klasa
'16' ok
'9' zly
'100' zly
'16.5' zly
'abc' zly
'' zly
&lt;b&gt;zle&lt;/b&gt;

Dla danych z samym imieniem (["imie" => "Jan"]) wszystkie pozostałe pola zgłaszają błąd, bo ich brak jest traktowany jak pusty tekst. Zadanie dla chętnych (rozszerzenie.php) wypisuje:

a@b.pl ok
a@b zly
@b.pl zly
a b@c.pl zly

Typowe błędy

ObjawCo sprawdzić
Warning: Undefined array keyOdczyt pola, którego nie przysłano; użyj ?? "".
Wiek 0 uznany za błąd mimo zakresu zawierającego 0Wynik filter_var porównano luźno (!$wiek) zamiast === false.
Polskie imię z dwoma znakami uznane za zbyt krótkieUżyto strlen, która liczy bajty; mb_strlen liczy znaki.
Błąd w in_array mimo poprawnej klasyBrak trybu ścisłego (true) albo porównywanie liczby z tekstem.
E-mail ze spacjami odrzuconyBrakuje trim przed filter_var.
Komunikat zawiera znaki < i psuje stronęKomunikat z danymi użytkownika wypisano bez htmlspecialchars.

Pytania kontrolne i punktacja

  1. Dlaczego walidacja tylko w przeglądarce nie wystarcza?
  2. Czym różni się strlen od mb_strlen?
  3. Co zwróci filter_var("abc", FILTER_VALIDATE_INT)?

Odpowiedzi: Bo użytkownik może ominąć kod w przeglądarce i wysłać dowolne dane bezpośrednio na serwer. strlen liczy bajty, mb_strlen — znaki. false.

Proponowana punktacja (razem 10 punktów): zadanie 1 — funkcja z czterema regułami 3 pkt, wynik dla danych poprawnych 1 pkt; zadanie 2 — cztery komunikaty 2 pkt; zadanie 3 — brakujące pola 1 pkt, filter_var z zakresem 2 pkt, htmlspecialchars 1 pkt. Zadanie dla chętnych nie jest wymagane do pełnej oceny.

Materiały do pobrania

Rozpakuj ZIP przed otwarciem plików. Materiały są dostępne bez logowania; publiczne rozwiązanie służy nauce i samodzielnemu sprawdzeniu, a nie poufnemu sprawdzianowi.

Co dalej?

Następny krok to ponowne wyświetlenie formularza z błędami i zapis poprawnych danych w bazie zapytaniem przygotowanym. Ten materiał rozwija dział o formularzach w kursie PHP w TablicaPro, gdzie znajdziesz prezentacje, ćwiczenia i testy do prowadzenia lekcji.

Źródła techniczne: filter_var w podręczniku PHP oraz filtry walidacyjne. Zobacz też lekcję o htmlspecialchars.

Poprowadź kolejne lekcje PHP

Pełny kurs: prezentacje, ćwiczenia i testy do pracy z klasą.

Kup dostęp do kursu PHP →

Zobacz program kursu