Skip to content

Blok 4

W bloku 3 okrążenie dodane formularzem znikało po odświeżeniu strony. Dziś zostaje, bo trafia do wspólnej bazy danych: okrążenie dodane przez jedną osobę widzą wszyscy. Zanim coś zapiszemy na stałe, trzeba sprawdzić, czy dane mają sens. Ujemna liczba kar skróciłaby czas zawodnika.

Trzy najczęstsze błędy w pracach z bloku 3. Literówka + 5 zamiast * 5 w liczeniu kar zmieniała każdą liczbę w tabeli. Zgubiony $liczbaElita++ dawał na stronie „elita: 0”. Nazwa pliku przepisana dosłownie z treści kosztowała punkt. Wniosek: przed oddaniem podstaw przykład z treści zadania, przewidź wynik i porównaj stronę przed zmianą i po niej.

Quiz z formularzy: kod i cztery odpowiedzi na slajdzie, każdy najpierw odpowiada sam.

Pytanie 1: pole formularza ma atrybuty name i id. Które z nich staje się kluczem w $_POST? Odpowiedź: b, $_POST['czas']. Do serwera trafia wartość pod kluczem z atrybutu name. Atrybut id służy tylko przeglądarce, a pole bez name nie zostanie wysłane.

Pytanie 2: formularz bez atrybutu method. Gdzie trafią dane? Odpowiedź: c. Formularz bez method wysyła dane metodą GET, więc lądują w adresie strony i w tablicy $_GET.

Pytanie 3: który adres przeniesie wybór kategorii na komputer kolegi? Odpowiedź: a. Metoda GET zapisuje dane w adresie, więc taki adres można wysłać dalej. Adres po POST nie zawiera danych. Zasada: GET do pytania o coś (filtr, wyszukiwanie), POST do zmiany czegoś (dodanie okrążenia).

Pytanie 4: co zawiera $_POST przy zwykłym otwarciu strony i czy isset($_POST) zwróci wtedy prawdę? Odpowiedź: d. Tablica $_POST istnieje zawsze, przy zwykłym otwarciu strony jest pusta, więc isset($_POST) zawsze zwraca true. Żeby sprawdzić, czy formularz został wysłany, pytamy o metodę żądania: $_SERVER['REQUEST_METHOD'] === 'POST'.

Pytanie 5: po dodaniu okrążenia formularzem POST wciskasz F5. Co zrobi przeglądarka i ile okrążeń pokaże strona? Odpowiedź: a. F5 powtarza ostatnie żądanie, a ostatnie było wysłaniem formularza, dlatego przeglądarka pyta o zgodę. W bloku 3 wynik to znowu 12, bo skrypt startuje od zera. Z bazą ponowne wysłanie dodałoby okrążenie drugi raz, dlatego w zadaniu B po zapisie strona przekierowuje na swój adres.

Pytanie 6: okrążenie trafia do tablicy dopiero po policzeniu licznika elity. Co pokaże tabela, a co licznik? Odpowiedź: c. Wiersze tabeli liczą się w HTML-u, już po dopisaniu, więc widzą nowe okrążenie. Licznik elity i stopka policzyły się wcześniej i go nie widzą. Kolejność w pliku: dane, obsługa formularza, liczenie, HTML.

Pytanie zapasowe: formularz nie ma atrybutu method, a obsługa w PHP sprawdza $_POST. Czy okrążenie zostanie dodane? Odpowiedź: d. Formularz wysłał dane metodą GET, więc $_POST jest pusty i warunek nie jest spełniony. PHP nie zgłasza błędu, jedynym śladem jest ?czas=250 w pasku adresu.

Pytanie zapasowe: co zwraca (int) na napisie, który nie jest liczbą, i na napisie, który zaczyna się od cyfr? Odpowiedź: b. (int) po cichu zamienia napis na liczbę: z "abc" robi 0, z "12abc" robi 12. Nie zgłasza błędu, więc nie nadaje się do sprawdzania danych. Najpierw sprawdzamy, czy napis to same cyfry, potem zamieniamy go na liczbę.

Teoria bloku 4: gdzie mogą być przechowywane dane między żądaniami i dlaczego dane z formularza trzeba sprawdzić po stronie serwera.

Dane mogą żyć w trzech miejscach. Zmienna PHP istnieje tylko podczas jednego żądania, dlatego okrążenie z bloku 3 znikało. Sesja pamięta dane jednej przeglądarki (blok 5). Baza danych przechowuje je na stałe i widzą je wszyscy, którzy się do niej łączą.

Atrybuty required i type="number" sprawdza przeglądarka. Użytkownik może je usunąć w narzędziach deweloperskich (F12) i wysłać cokolwiek, na przykład abc. Służą wygodzie użytkownika, nie ochronie serwera. Dane trzeba sprawdzić w PHP, zanim się ich użyje albo zapisze.

Droga danych z formularza: wszystko, co przychodzi w $_POST, jest napisem. Najpierw sprawdzamy, czy napis ma sens, potem zamieniamy go na liczbę przez (int) i używamy. Dane, które nie przeszły sprawdzenia, nie trafiają dalej, a strona pokazuje komunikat o błędzie.

Zadanie A: dodaj okrążenie, ale bezpiecznie

Section titled “Zadanie A: dodaj okrążenie, ale bezpiecznie”

Zadanie A: starter zawody-starter-4.zip zawiera dane i funkcje z bloku 3, tabelę i gotowy formularz. Plik trzeba nazwać nazwisko_imie_blok4.php. Obsługę formularza piszesz w sekcji // ===== OBSŁUGA FORMULARZA =====, która stoi nad liczeniem wyników. Obsługa działa tylko po wysłaniu formularza, czyli gdy $_SERVER['REQUEST_METHOD'] === 'POST'. Pełna treść w sekcji Zadania.

Obsługa sprawdza trzy pola, każde z własnym komunikatem w zmiennej $blad: zawodnik musi być liczbą całkowitą i numerem istniejącego zawodnika, czas liczbą całkowitą od 60 do 900 sekund, kary liczbą całkowitą od 0 do 10. Po złym wpisie okrążenie się nie dodaje, a nad formularzem widać komunikat. Dobre okrążenie trafia do tablicy przed liczeniem, więc widzą je tabela, licznik elity i podsumowanie.

Wzór walidacji jednego pola na przykładzie wieku. ctype_digit($tekst) sprawdza, czy napis składa się z samych cyfr, więc odpada minus, kropka i puste pole. Dopiero tak sprawdzony napis zamieniamy przez (int) i porównujemy z zakresem. Każdy błąd wpisuje komunikat do $blad, a danych używamy dopiero wtedy, gdy $blad jest pusty.

Sesja robocza nad zadaniem A. Najpierw poprawne okrążenie: Fijałek, 250 sekund, bez kar, a na stronie 12 okrążeń i trzech zawodników w elicie. Potem po kolei złe wartości: abc, 30, 1000, -1, 11. Po każdej zostaje 11 okrążeń i widać komunikat. Rozszerzenie: obsłużyć żądanie, w którym jednego z pól w ogóle nie ma w $_POST.

Godzina trzecia: jedna wspólna baza danych MySQL na serwerze, do której łączy się cała sala. Dane są te same co w starterze.

Baza ma dwie tabele. zawodnicy ma kolumny id (numery 0–4, te same co indeksy tablicy w zadaniu A) i nazwa. okrazenia ma id nadawane automatycznie, zawodnik_id wskazujący zawodnika, czas, kary i dodano, czyli czas dodania wpisywany automatycznie. Konto uczniowskie może odczytywać obie tabele i dopisywać okrążenia, nic więcej.

Połączenie z bazą to trzy linie. mysqli_report(...) sprawia, że każdy błąd bazy zatrzymuje skrypt z czytelnym komunikatem, niezależnie od wersji PHP. mysqli_connect(...) łączy się z serwerem: użytkownik to zs1, baza to zawody, a host i hasło prowadzący podaje na zajęciach. mysqli_set_charset($db, 'utf8mb4') ustawia kodowanie, żeby polskie znaki nie zamieniły się w krzaczki.

mysqli_query wysyła zapytanie SQL do bazy, a mysqli_fetch_assoc zwraca kolejny wiersz wyniku jako tablicę, w której kluczami są nazwy kolumn. Pętla while bierze wiersze po jednym, aż się skończą. Liczby z bazy też przychodzą jako napisy.

Poprawne okrążenie z formularza zapisujemy do bazy zapytaniem INSERT INTO okrazenia (zawodnik_id, czas, kary) VALUES (...). Do zapytania trafiają wyłącznie wartości, które przeszły walidację z zadania A i zostały zamienione na liczby przez (int), nic prosto z $_POST. Zaraz po zapisie strona przekierowuje przeglądarkę na swój adres: header('Location: ' . $_SERVER['PHP_SELF']); i exit;. Bez tego F5 wysłałby formularz drugi raz i dodał drugie okrążenie. Bezpieczny sposób na zapisywanie napisów poznamy przy logowaniu.

Zadanie B: w kopii pliku z zadania A, nazwanej nazwisko_imie_baza_blok4.php, tablica $zawodnicy przestaje być wpisana w kod. Powstaje z dwóch zapytań SELECT, do tabeli zawodnicy i do tabeli okrazenia, w tym samym kształcie co w zadaniu A, więc funkcje i tabela działają bez zmian. Dobre okrążenie z formularza idzie do bazy INSERT-em, a strona przekierowuje na swój adres. Zanim ktoś doda okrążenie, strona wygląda tak samo jak w zadaniu A. Zadanie jest bez punktów i robione wspólnie na lekcji.

Kolejność w pliku zadania B: połączenie z bazą, SELECT zawodników, obsługa formularza, SELECT okrążeń, liczenie wyników, HTML. Zawodników trzeba pobrać przed obsługą formularza, bo walidacja sprawdza, czy zawodnik istnieje. Okrążenia pobieramy po niej, żeby nowe okrążenie było już w wyniku.

Demonstracja: prowadzący dodaje okrążenie ze swojego komputera, a uczniowie po odświeżeniu własnych stron z zadania B widzą je u siebie. Skrypt dalej startuje od zera przy każdym żądaniu, ale dane pobiera ze wspólnej bazy, więc to, co ktoś do niej zapisał, zostaje.

Sprawdzenie zadania B: po dodaniu okrążenia i F5 na stronie jest jedno nowe okrążenie, bez pytania przeglądarki o ponowne wysłanie, a sąsiad widzi je u siebie. Rozszerzenie: lista pięciu ostatnio dodanych okrążeń pod tabelą, od najnowszego (ORDER BY dodano DESC, id DESC LIMIT 5).

Oddanie dwóch plików: nazwisko_imie_blok4.php (zadanie A) i nazwisko_imie_baza_blok4.php (zadanie B, przeglądane). W nazwie własne nazwisko i imię, małe litery, bez polskich znaków. Przed wysłaniem sprawdź, czy dobre okrążenie się dodaje, czy złe dane pokazują komunikat i czy strona otwiera się po odświeżeniu. Grupa 1 wypycha pliki do swojego repozytorium, grupa 2 wysyła na Teams.

Zapowiedź bloku 5: baza danych pamięta dane dla wszystkich jednakowo. Żeby strona pamiętała coś tylko dla jednej osoby, na przykład kto jest zalogowany, potrzebna jest sesja.

Koniec bloku.