Blok 4
Okrążenie, które zniknęło
Section titled “Okrążenie, które zniknęło”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.
Blok 3: co poszło nie tak
Section titled “Blok 3: co poszło nie tak”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
Section titled “Quiz z formularzy”Quiz z formularzy: kod i cztery odpowiedzi na slajdzie, każdy najpierw odpowiada sam.
1. Pod jakim kluczem?
Section titled “1. Pod jakim kluczem?”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.
2. Gdzie lądują dane?
Section titled “2. Gdzie lądują dane?”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.
3. Który adres wyślesz koledze?
Section titled “3. Który adres wyślesz koledze?”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).
4. Pierwsze wejście na stronę
Section titled “4. Pierwsze wejście na stronę”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'.
5. Dodałeś okrążenie. Wciskasz F5
Section titled “5. Dodałeś okrążenie. Wciskasz F5”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.
6. Okrążenie dopisane za późno
Section titled “6. Okrążenie dopisane za późno”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.
7. Zapasowe: czy okrążenie się doda?
Section titled “7. Zapasowe: czy okrążenie się doda?”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.
8. Zapasowe: co wypisze?
Section titled “8. Zapasowe: co wypisze?”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ę.
Gdzie żyje okrążenie
Section titled “Gdzie żyje okrążenie”Teoria bloku 4: gdzie mogą być przechowywane dane między żądaniami i dlaczego dane z formularza trzeba sprawdzić po stronie serwera.
Trzy miejsca na dane
Section titled “Trzy miejsca na dane”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ą.
required to nie walidacja
Section titled “required to nie walidacja”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.
Sprawdza serwer, bo tylko jemu ufasz
Section titled “Sprawdza serwer, bo tylko jemu ufasz”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.
Trzy reguły, trzy komunikaty
Section titled “Trzy reguły, trzy komunikaty”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.
Jedno pole na próbę: wiek
Section titled “Jedno pole na próbę: wiek”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: zadanie A
Section titled “Sesja robocza: zadanie A”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.
Baza: jedna na całą salę
Section titled “Baza: jedna na całą salę”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.
Dwie tabele
Section titled “Dwie tabele”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: trzy linie
Section titled “Połączenie: trzy linie”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.
Odczyt: SELECT i pętla
Section titled “Odczyt: SELECT i pętla”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.
Zapis: INSERT z formularza
Section titled “Zapis: INSERT z formularza”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: okrążenia z bazy
Section titled “Zadanie B: okrążenia z bazy”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
Section titled “Kolejność w pliku”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.
Odśwież swoją stronę
Section titled “Odśwież swoją stronę”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.
Sprawdź, czy zostało
Section titled “Sprawdź, czy zostało”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
Section titled “Oddanie”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.
Za tydzień: kim jesteś?
Section titled “Za tydzień: kim jesteś?”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.
Wolna końcówka
Section titled “Wolna końcówka”Koniec bloku.