Przejdź do głównej treści
INF.03-03-22.06-SGCzerwiec 2022 · 37 kroków · ok. 77 min · 35 kryteriów z klucza

Rozwiązanie krok po kroku: Portal zawodów wędkarskich (Nowoczesny kod (grid, PDO))

To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza wedkarstwo z czterema zapytaniami, odbite i przeskalowane zdjęcie, strona zawody.html z formularzem i skrypt zgloszenie.php, który dopisuje zawody do bazy - i tak samo spełnia każde kryterium klucza. Inna jest droga:

  • dwie siatki CSS zamiast float: bloki lewy i prawy stoją w znaczniku <header> z kolumnami 75% i 25%, a dwa bloki stopki w <footer> z kolumnami 50% i 50% - klucz wprost dopuszcza szerokości w grid-template-columns, a blok główny nie potrzebuje clear,
  • zmienne CSS dla kolorów z arkusza, wiersze formularza w blokach <div> zamiast <br>, przyciski <button>,
  • skrypt na PDO: dane z formularza są sprawdzane (łowisko musi istnieć w tabeli lowisko, data musi być prawdziwa, sędzia wpisany), a do bazy trafiają zapytaniem przygotowanym,
  • skrypt wypisuje wynik (arkusz tego nie wymaga, a pusta strona nic nie mówi użytkownikowi) przez funkcję e() (htmlspecialchars) i stosuje wzorzec PRG - odświeżenie strony nie dodaje zawodów drugi raz,
  • zapytania z listą kolumn w INSERT i aliasami tabel w złączeniu.

Na końcu krótkie porównanie z wersją podstawową (zakładka obok). Baza i zdjęcie pochodzą z prawdziwego archiwum pliki3.zip, a podgląd skryptu to wynik prawdziwego uruchomienia kodu w PHP na bazie z arkusza.

Jak liczą się punkty. Klucz ma 35 kryteriów (R.1.1 - R.5.5), każde za 1 punkt. Próg zdania to 75%, czyli 27 punktów. Przy każdym kroku jest napisane, które kryteria spełnia.

  1. Etap 1: Baza danych

    Kroki 1-7 · po tym etapie masz 6 z 35 kryteriów (pkt)

    Krok 1: Baza danych wedkarstwo

    ok. 2 min
    Polecenie z arkusza

    Utwórz bazę danych o nazwie wedkarstwo

    Rozpakuj pliki3.zip z pulpitu (hasło ZaWodY7% - wielkość liter ma znaczenie, na końcu znak procentu) do folderu z numerem zdającego: baza.sql i zawody.jpg. W phpMyAdmin Nowa → wedkarstwo albo zapytaniem:

    CREATE DATABASE wedkarstwo CHARACTER SET utf8mb4 COLLATE utf8mb4_polish_ci;
    

    Arkusz nie podaje porównywania, więc wybór należy do Ciebie. Tabele z baza.sql mają zestaw znaków (latin1) zapisany we własnej definicji, więc ustawienie bazy ich nie zmienia - ma to skutek przy zapisie z formularza (krok z zapytaniem w skrypcie).

    Typowe błędy

    Nazwa bazy musi brzmieć dokładnie wedkarstwo - skrypt łączy się z bazą po nazwie (R.5.1).

  2. Krok 2: Import tabel z pliku baza.sql

    ok. 2 min
    Polecenie z arkusza

    Do bazy wedkarstwo zaimportuj tabele z pliku baza.sql z rozpakowanego archiwum

    Przy zaznaczonej bazie wedkarstwo: Import → baza.sql → Wykonaj. Zadanie korzysta z trzech tabel z obrazu 1: zawody_wedkarskie (zawody: zwycięzca Karty_wedkarskie_id, łowisko Lowisko_id, data, sędzia), karty_wedkarskie (wędkarze) i lowisko (rodzaj: 1 morze, 2 jezioro, 3 rzeka, 4 zalew, 5 staw).

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

    R.1.1 Wykonano import tabel do bazy danych wedkarstwo czynność udokumentowano plikiem o nazwie import w formacie PNG

    ok. 2 min
    Polecenie z arkusza

    Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w formacie PNG i nazwij import. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel

    Print Screen, cały ekran z paskiem zadań, zapis jako import.png. Uwaga na formaty: import idzie do PNG, a zrzuty zapytań do JPEG.

    Typowe błędy

    Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).

  4. Krok 4: Zapytanie 1: nowe zawody (INSERT)

    Kryteria: ,

    R.1.2 Zapisano plik o nazwie kwerendy.txt zawierający co najmniej jedno zapytanie SQL, wynikające z treści zadania

    R.1.3 Utworzono zapytanie 1 dodające rekord do tabeli zawody_wedkarskie o wartościach: klucz główny nadawany automatycznie, 2, 4, „2021-09-28”, Andrzej Nowak. W pliku z kwerendami lub na zrzucie istnieje zapis np.: INSERT INTO zawody_wedkarskie VALUES (NULL, '2', '4', '2021-09- 28', 'Andrzej Nowak');(możliwe różne warianty INSERT INTO) oraz wynik działania udokumentowano zrzutem, na którym widoczny jest komunikat o poprawnym dodaniu rekordu lub tabela z dodanym rekordem

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 1: wstawiające rekord do tabeli zawody_wedkarskie o wartościach: klucz główny nadawany automatycznie, Karty_wedkarskie_id - 2; Lowisko_id - 4; data_zawodow - „2021-09-28”; sedzia – Andrzej Nowak

    INSERT INTO z jawną listą kolumn: po nazwie tabeli cztery kolumny, po VALUES wartości w tej samej kolejności. Kolumny id nie ma na liście - ma AUTO_INCREMENT, więc baza nada jej następny numer sama (tu 5). Lista kolumn sprawia, że zapytanie nie zależy od kolejności kolumn w tabeli i od razu widać, która liczba trafia gdzie. Liczby bez apostrofów, data i tekst w apostrofach. Klucz uznaje „różne warianty INSERT INTO”. Zapytanie do kwerendy.txt, zrzut kw1.jpg.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    INSERT INTO zawody_wedkarskie (Karty_wedkarskie_id, Lowisko_id, data_zawodow, sedzia)
    VALUES (2, 4, '2021-09-28', 'Andrzej Nowak');
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: zawody sędziego Krzysztofa Dobrowolskiego

    Kryteria:

    R.1.4 Utworzono zapytanie 2 wybierające jedynie pola id oraz data_zawodow z tabeli zawody_wedkarskie dla sędziego Krzysztofa Dobrowolskiego . W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id, data_zawodow FROM zawody_wedkarskie WHERE sedzia = 'Krzysztof Dobrowolski'; oraz wynik działania udokumentowano zrzutem, na którym widoczny jest tylko jeden rekord: 4, 2018-06-21

    ok. 1 min
    Polecenie z arkusza

    Zapytanie 2: wybierające jedynie pola id oraz data_zawodow z tabeli zawody_wedkarskie dla sędziego Krzysztofa Dobrowolskiego

    W bazie imię i nazwisko sędziego są w jednym polu, w mianowniku: sedzia = 'Krzysztof Dobrowolski'. Wynik (sprawdzony na bazie z archiwum): jeden wiersz 4, 2018-06-21 - jak w kluczu. Zrzut kw2.jpg.

    kwerendy.txt Tekst zmienione: 5 linii
    -- Zapytanie 1
    INSERT INTO zawody_wedkarskie (Karty_wedkarskie_id, Lowisko_id, data_zawodow, sedzia)
    VALUES (2, 4, '2021-09-28', 'Andrzej Nowak');
    
    -- Zapytanie 2
    SELECT id, data_zawodow
    FROM zawody_wedkarskie
    WHERE sedzia = 'Krzysztof Dobrowolski';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: zwycięzca zawodów numer 4

    Kryteria:

    R.1.5 Utworzono zapytanie 3 wybierające jedynie pola imię, nazwisko i punkty z tabeli karty_wedkarskie dla zwycięzcy zawodów wędkarskich o identyfikatorze zawody_wedkarskie.id=4. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, nazwisko, punkty FROM karty_wedkarskie JOIN zawody_wedkarskie ON karty_wedkarskie.id = zawody_wedkarskie.Karty_wedkarskie_id WHERE zawody_wedkarskie.id = 4; (możliwe też INNER JOIN lub przyrównanie kluczy w WHERE) oraz wynik działania udokumentowano zrzutem, na którym widoczny jest tylko jeden rekord z danymi: Andrzej Nowak, 3

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie pola imie, nazwisko i punkty z tabeli karty_wedkarskie dla zwycięzcy zawodów wędkarskich o identyfikatorze 4 (identyfikator dotyczy zawodów, a nie wędkarza), należy użyć relacji

    • aliasy tabel k (karty) i z (zawody) - obie tabele mają kolumnę id, a przedrostek mówi wprost, o które id chodzi,
    • JOIN ... ON z.Karty_wedkarskie_id = k.id - relacja z obrazu 1: zawody wskazują swojego zwycięzcę,
    • WHERE z.id = 4 - numer zawodów, nie wędkarza (przed tym ostrzega nawias w arkuszu).

    Wynik: Andrzej Nowak 3 - jak w kluczu. Zrzut kw3.jpg.

    Typowe błędy

    WHERE k.id = 4 (numer wędkarza) daje pusty wynik - w bazie są tylko dwaj wędkarze.

    kwerendy.txt Tekst zmienione: 6 linii
    -- Zapytanie 1
    INSERT INTO zawody_wedkarskie (Karty_wedkarskie_id, Lowisko_id, data_zawodow, sedzia)
    VALUES (2, 4, '2021-09-28', 'Andrzej Nowak');
    
    -- Zapytanie 2
    SELECT id, data_zawodow
    FROM zawody_wedkarskie
    WHERE sedzia = 'Krzysztof Dobrowolski';
    
    -- Zapytanie 3
    SELECT k.imie, k.nazwisko, k.punkty
    FROM karty_wedkarskie AS k
    JOIN zawody_wedkarskie AS z ON z.Karty_wedkarskie_id = k.id
    WHERE z.id = 4;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: dwa punkty więcej dla wędkarza numer 1

    Kryteria:

    R.1.6 Utworzono zapytanie 4 aktualizujące dane w tabeli karty_wedkarskie , wartość pola punkty jedynie dla rekordu o identyfikatorze 1 należy zwiększyć o 2. W pliku z kwerendami lub na zrzucie istnieje zapis np.: UPDATE karty_wedkarskie SET punkty = punkty + 2 WHERE karty_wedkarskie.id = 1; oraz wynik działania udokumentowano zrzutem, na którym widoczny jest komunikat o poprawnej aktualizacji lub tabela ze zmienioną wartością

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 4: aktualizujące dane w tabeli karty_wedkarskie, wartość pola punkty dla rekordu o identyfikatorze 1 należy zwiększyć o 2

    SET punkty = punkty + 2 - nowa wartość liczona ze starej, nie trzeba znać aktualnej liczby punktów; WHERE id = 1 - tylko Jan Kowalski. Miał 23 punkty, po zapytaniu ma 25. Zrzut kw4.jpg: komunikat i tabela po zmianie.

    Typowe błędy

    SET punkty = 25 daje dziś ten sam wynik, ale nie jest „zwiększeniem o 2” - klucz wymaga zapytania uniwersalnego.

    kwerendy.txt Tekst zmienione: 5 linii
    -- Zapytanie 1
    INSERT INTO zawody_wedkarskie (Karty_wedkarskie_id, Lowisko_id, data_zawodow, sedzia)
    VALUES (2, 4, '2021-09-28', 'Andrzej Nowak');
    
    -- Zapytanie 2
    SELECT id, data_zawodow
    FROM zawody_wedkarskie
    WHERE sedzia = 'Krzysztof Dobrowolski';
    
    -- Zapytanie 3
    SELECT k.imie, k.nazwisko, k.punkty
    FROM karty_wedkarskie AS k
    JOIN zawody_wedkarskie AS z ON z.Karty_wedkarskie_id = k.id
    WHERE z.id = 4;
    
    -- Zapytanie 4
    UPDATE karty_wedkarskie
    SET punkty = punkty + 2
    WHERE id = 1;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Grafika i strona HTML

    Kroki 8-22 · po tym etapie masz 19 z 35 kryteriów (pkt)

    Krok 8: Zdjęcie zawody.jpg: odbicie i wysokość 250 px

    Kryteria:

    R.2.1 Grafikę z pliku o nazwie zawody.jpg odbito w taki sposób, aby osoba na grafice znajdowała się po prawej stronie jak na obrazie 2 oraz przeskalowano z zachowaniem proporcji do wysokości 250 px. Odpowiadająca temu szerokość wynosi 251 px (± 2 px)

    ok. 3 min
    Polecenie z arkusza

    Plik zawody.jpg, wypakowany z archiwum, należy odbić w taki sposób, aby osoba na grafice znajdowała się po prawej stronie, jak na obrazie 2 oraz przeskalować z zachowaniem proporcji tak, aby jego wysokość wynosiła dokładnie 250 px i zapisać pod tą samą nazwą

    Grafika jest taka sama jak w wersji podstawowej. W GIMP-ie Obraz → Przekształć → Odbij poziomo (wędkarz przechodzi na prawą stronę) i Obraz → Skaluj obraz z zamkniętym łańcuchem proporcji, wysokość 250 px - szerokość wyjdzie 251 px (415 × 413 px na wejściu), jak w kluczu (±2 px). Na koniec Plik → Nadpisz zawody.jpg.

    Typowe błędy

    Odbij pionowo stawia wędkarza do góry nogami - potrzebne jest odbicie w poziomie.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Plik zawody.html: HTML5, język, kodowanie

    Kryteria:

    R.2.2 Witrynę internetową zapisano w pliku o nazwie zawody.html oraz zapisano jawnie standard kodowania polskich znaków i deklarację HTML5 <!DOCTYPE HTML> oraz zadeklarowano dla witryny język polski

    ok. 2 min
    Polecenie z arkusza

    Składa się ze strony o nazwie zawody.html zapisanej w języku HTML 5 oraz skryptu zgloszenie.php. Poniższe wymagania dotyczą tylko pliku zawody.html. Zadeklarowany język dla witryny: polski. Jawnie zastosowany właściwy standard kodowania polskich znaków

    <!DOCTYPE html>, <html lang="pl"> i <meta charset="UTF-8"> jako pierwszy element <head> (R.2.2). Strona nie ma kodu PHP, więc ma rozszerzenie .html. Formularz zadziała tylko wtedy, gdy strona jest otwarta przez serwer XAMPP (http://localhost/...) - inaczej po wysłaniu przeglądarka pokaże kod PHP zamiast go wykonać.

    zawody.html HTML nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (zawody.html)
  10. Krok 10: Tytuł strony

    Kryteria:

    R.2.3 Nadano tytuł strony: Zawody wędkarskie

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Zawody wędkarskie”

    <title> (R.2.3) i viewport - telefon nie pomniejsza strony do szerokości ekranu komputera.

    zawody.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Zawody wędkarskie</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (zawody.html)
  11. Krok 11: Podpięcie arkusza stylów

    Kryteria:

    R.3.6 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl3.css , formatowanie pochodzi jedynie z tego arkusza Uwaga: kryterium to nie jest spełnione również, gdy zdający źle przypisał co najmniej jeden selektor do bloku (np. kropka zamiast #)

    ok. 1 min
    Polecenie z arkusza

    Arkusz stylów w pliku o nazwie styl3.css prawidłowo połączony z kodem strony

    Nazwa pliku: styl3.css - z cyfrą 3. Całe formatowanie pochodzi z tego pliku, bez atrybutów style (R.3.6).

    Typowe błędy

    Klucz odbiera R.3.6 także wtedy, gdy choć jeden selektor nie trafia w blok (np. kropka zamiast #).

    zawody.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (zawody.html)
  12. Krok 12: Bloki: lewy i prawy w header, główny, dwie stopki w footer

    Kryteria:

    R.2.4 Układ strony zdefiniowano dzieląc ją na bloki: lewy, prawy, główny i dwa bloki stopki. Zastosowano znaczniki sekcji

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: na górze dwa bloki: lewy i prawy, poniżej blok główny, na dole dwa bloki stopki. Podział zrealizowany za pomocą znaczników sekcji tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z obrazem 2

    Strona ma trzy pasy, więc trzy główne znaczniki:

    • <header> - górny pas, a w nim dwa bloki <section>: lewy #title (nazwa portalu) i prawy #photo (zdjęcie),
    • <main> - blok główny z listą łowisk i formularzem,
    • <footer> - dolny pas, a w nim dwa bloki stopki: #downloads (odnośnik do kwerend) i #author (autor strony).

    Pary bloków stoją we wspólnym rodzicu, więc w CSS każdy pas dostanie własną siatkę z kolumnami - bez float i clear. Wszystkie bloki to znaczniki sekcji HTML5 (R.2.4).

    zawody.html HTML zmienione: 14 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <section id="title">
            </section>
            <section id="photo">
            </section>
        </header>
        <main>
        </main>
        <footer>
            <section id="downloads">
            </section>
            <section id="author">
            </section>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (zawody.html)
  13. Krok 13: Blok lewy: nagłówek

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku lewego: nagłówek pierwszego stopnia o treści „Zawody polskich wędkarzy”

    <h1> w bloku lewym.

    zawody.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <section id="title">
                <h1>Zawody polskich wędkarzy</h1>
            </section>
            <section id="photo">
            </section>
        </header>
        <main>
        </main>
        <footer>
            <section id="downloads">
            </section>
            <section id="author">
            </section>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (zawody.html)
  14. Krok 14: Blok prawy: zdjęcie

    Kryteria:

    R.2.7 W bloku prawym umieszczono obraz zawody.jpg z tekstem alternatywnym "wędkowanie"

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku prawego: obraz zawody.jpg z tekstem alternatywnym o treści: „wędkowanie”

    <img> z odbitym i przeskalowanym zdjęciem; tekst alternatywny z arkusza, z polską literą „ę” (R.2.7).

    zawody.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <section id="title">
                <h1>Zawody polskich wędkarzy</h1>
            </section>
            <section id="photo">
                <img src="zawody.jpg" alt="wędkowanie">
            </section>
        </header>
        <main>
        </main>
        <footer>
            <section id="downloads">
            </section>
            <section id="author">
            </section>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (zawody.html)
  15. Krok 15: Blok główny: nagłówek i lista łowisk

    Kryteria:

    R.2.6 W bloku głównym umieszczono listę punktową z czterema elementami, zastosowano znaczniki <ul>, <li>

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloku głównego: Nagłówek trzeciego stopnia o treści: „Łowiska”. Lista punktowana (nieuporządkowana) zawierająca elementy: Zalew Węgrowski, Zbiornik Bukówka, Jeziorko Bartbetowskie, Warta-Obrzycko

    <h3> - stopień nagłówka bierzesz z arkusza, nie z hierarchii strony. Lista punktowana to <ul> z czterema <li> (R.2.6); nazwy z polskimi literami, tak jak w arkuszu (w tabeli lowisko są zapisane bez nich).

    zawody.html HTML zmienione: 7 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <section id="title">
                <h1>Zawody polskich wędkarzy</h1>
            </section>
            <section id="photo">
                <img src="zawody.jpg" alt="wędkowanie">
            </section>
        </header>
        <main>
            <h3>Łowiska</h3>
            <ul>
                <li>Zalew Węgrowski</li>
                <li>Zbiornik Bukówka</li>
                <li>Jeziorko Bartbetowskie</li>
                <li>Warta-Obrzycko</li>
            </ul>
        </main>
        <footer>
            <section id="downloads">
            </section>
            <section id="author">
            </section>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (zawody.html)
  16. Krok 16: Blok główny: formularz POST do zgloszenie.php

    Kryteria:

    R.3.5 Formularz wysyła dane metodą POST do skryptu zgloszenie.php

    ok. 2 min
    Polecenie z arkusza

    Nagłówek trzeciego stopnia o treści: „Dodaj zawody wędkarskie”. Formularz wysyłający dane metodą bezpieczną do pliku zgloszenie.php zawierający pola

    Drugi <h3> i <form> z action="zgloszenie.php" (dokąd trafią dane) i method="post" (R.3.5) - dane idą w treści żądania, a nie w adresie strony.

    ⚠️ Rozbieżność arkusz-klucz: arkusz każe wysyłać dane „metodą bezpieczną”, a w specyfikacji HTTP (RFC 9110) metody bezpieczne (safe) to GET i HEAD - te, które nie zmieniają danych na serwerze. Klucz CKE (R.3.5) wymaga POST - na egzaminie punkt daje wersja z klucza. Tu POST jest zresztą właściwy także według HTTP: formularz dopisuje dane do bazy.

    Typowe błędy

    Formularz bez method wysyła dane metodą GET - skrypt czytający $_POST niczego nie dostanie, a R.3.5 nie jest spełnione.

    zawody.html HTML zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <section id="title">
                <h1>Zawody polskich wędkarzy</h1>
            </section>
            <section id="photo">
                <img src="zawody.jpg" alt="wędkowanie">
            </section>
        </header>
        <main>
            <h3>Łowiska</h3>
            <ul>
                <li>Zalew Węgrowski</li>
                <li>Zbiornik Bukówka</li>
                <li>Jeziorko Bartbetowskie</li>
                <li>Warta-Obrzycko</li>
            </ul>
            <h3>Dodaj zawody wędkarskie</h3>
            <form action="zgloszenie.php" method="post">
            </form>
        </main>
        <footer>
            <section id="downloads">
            </section>
            <section id="author">
            </section>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (zawody.html)
  17. Krok 17: Formularz: pole liczbowe „Łowisko”

    ok. 2 min
    Polecenie z arkusza

    Pole edycyjne typu numerycznego poprzedzone tekstem: „Łowisko: ”

    Napis w <label> przed polem, para we własnym bloku <div> - kolejne pole zacznie się od nowej linii bez <br>. <input type="number"> z name="fishery" - pod tą nazwą wartość trafi do $_POST. min="1" i required - przeglądarka nie wyśle pustego pola ani zera. To wygoda dla użytkownika, nie zabezpieczenie: skrypt i tak sprawdzi, czy takie łowisko istnieje.

    zawody.html HTML zmienione: 4 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <section id="title">
                <h1>Zawody polskich wędkarzy</h1>
            </section>
            <section id="photo">
                <img src="zawody.jpg" alt="wędkowanie">
            </section>
        </header>
        <main>
            <h3>Łowiska</h3>
            <ul>
                <li>Zalew Węgrowski</li>
                <li>Zbiornik Bukówka</li>
                <li>Jeziorko Bartbetowskie</li>
                <li>Warta-Obrzycko</li>
            </ul>
            <h3>Dodaj zawody wędkarskie</h3>
            <form action="zgloszenie.php" method="post">
                <div>
                    <label for="fishery">Łowisko: </label>
                    <input type="number" id="fishery" name="fishery" min="1" required>
                </div>
            </form>
        </main>
        <footer>
            <section id="downloads">
            </section>
            <section id="author">
            </section>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (zawody.html)
  18. Krok 18: Formularz: pole daty z kalendarzem

    Kryteria:

    R.3.3 Jedno pole edycyjne jest typu numerycznego, drugie typu date

    ok. 1 min
    Polecenie z arkusza

    Pole edycyjne umożliwiające wybranie daty z kalendarza, poprzedzone tekstem: „Data: ”

    <input type="date"> - przeglądarka pokazuje kalendarz. Na ekranie data ma format zależny od języka systemu (np. dd.mm.rrrr), ale do skryptu zawsze trafia jako 2021-10-02 - tak, jak potrzebuje pole DATE w bazie. Pole liczbowe i pole daty są gotowe (R.3.3).

    zawody.html HTML zmienione: 4 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <section id="title">
                <h1>Zawody polskich wędkarzy</h1>
            </section>
            <section id="photo">
                <img src="zawody.jpg" alt="wędkowanie">
            </section>
        </header>
        <main>
            <h3>Łowiska</h3>
            <ul>
                <li>Zalew Węgrowski</li>
                <li>Zbiornik Bukówka</li>
                <li>Jeziorko Bartbetowskie</li>
                <li>Warta-Obrzycko</li>
            </ul>
            <h3>Dodaj zawody wędkarskie</h3>
            <form action="zgloszenie.php" method="post">
                <div>
                    <label for="fishery">Łowisko: </label>
                    <input type="number" id="fishery" name="fishery" min="1" required>
                </div>
                <div>
                    <label for="date">Data: </label>
                    <input type="date" id="date" name="date" required>
                </div>
            </form>
        </main>
        <footer>
            <section id="downloads">
            </section>
            <section id="author">
            </section>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (zawody.html)
  19. Krok 19: Formularz: pole „Sędzia”

    ok. 1 min
    Polecenie z arkusza

    Pole edycyjne poprzedzone tekstem: „Sędzia: ”

    Zwykłe pole tekstowe z nazwą referee. autocomplete="name" podpowiada przeglądarce, że chodzi o imię i nazwisko.

    zawody.html HTML zmienione: 4 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <section id="title">
                <h1>Zawody polskich wędkarzy</h1>
            </section>
            <section id="photo">
                <img src="zawody.jpg" alt="wędkowanie">
            </section>
        </header>
        <main>
            <h3>Łowiska</h3>
            <ul>
                <li>Zalew Węgrowski</li>
                <li>Zbiornik Bukówka</li>
                <li>Jeziorko Bartbetowskie</li>
                <li>Warta-Obrzycko</li>
            </ul>
            <h3>Dodaj zawody wędkarskie</h3>
            <form action="zgloszenie.php" method="post">
                <div>
                    <label for="fishery">Łowisko: </label>
                    <input type="number" id="fishery" name="fishery" min="1" required>
                </div>
                <div>
                    <label for="date">Data: </label>
                    <input type="date" id="date" name="date" required>
                </div>
                <div>
                    <label for="referee">Sędzia: </label>
                    <input type="text" id="referee" name="referee" autocomplete="name" required>
                </div>
            </form>
        </main>
        <footer>
            <section id="downloads">
            </section>
            <section id="author">
            </section>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (zawody.html)
  20. Krok 20: Formularz: przyciski CZYŚĆ i DODAJ

    Kryteria: ,

    R.2.8 W bloku głównym umieszczono formularz z trzema polami edycyjnymi i dwoma przyciskami, zastosowano znacznik <form>

    R.3.4 Jeden przycisk czyści dane formularza, drugi wysyła dane do skryptu (input lub button z typem submit lub button bez typu)

    ok. 2 min
    Polecenie z arkusza

    Przycisk czyszczący zawartość formularza z etykietą „CZYŚĆ”. Przycisk wysyłający zawartość formularza z etykietą „DODAJ”

    Działanie przycisku zależy od typu: type="reset" przywraca pola do stanu początkowego bez żadnego skryptu, type="submit" wysyła formularz pod adres z action (R.3.4). Znacznik <button> ma napis między znacznikami, a nie w atrybucie value - w środku może stać też np. ikona. Formularz ma trzy pola i dwa przyciski (R.2.8).

    zawody.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <section id="title">
                <h1>Zawody polskich wędkarzy</h1>
            </section>
            <section id="photo">
                <img src="zawody.jpg" alt="wędkowanie">
            </section>
        </header>
        <main>
            <h3>Łowiska</h3>
            <ul>
                <li>Zalew Węgrowski</li>
                <li>Zbiornik Bukówka</li>
                <li>Jeziorko Bartbetowskie</li>
                <li>Warta-Obrzycko</li>
            </ul>
            <h3>Dodaj zawody wędkarskie</h3>
            <form action="zgloszenie.php" method="post">
                <div>
                    <label for="fishery">Łowisko: </label>
                    <input type="number" id="fishery" name="fishery" min="1" required>
                </div>
                <div>
                    <label for="date">Data: </label>
                    <input type="date" id="date" name="date" required>
                </div>
                <div>
                    <label for="referee">Sędzia: </label>
                    <input type="text" id="referee" name="referee" autocomplete="name" required>
                </div>
                <button type="reset">CZYŚĆ</button>
                <button type="submit">DODAJ</button>
            </form>
        </main>
        <footer>
            <section id="downloads">
            </section>
            <section id="author">
            </section>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (zawody.html)
  21. Krok 21: Pierwszy blok stopki: odnośnik do kwerendy.txt

    Kryteria:

    R.3.2 Po wybraniu odnośnika "Pobierz" otwiera się lub pobiera plik kwerendy.txt

    ok. 1 min
    Polecenie z arkusza

    Zawartość pierwszego bloku stopki: odnośnik do pliku kwerendy.txt o treści: „Pobierz”

    href z nazwą pliku z tego samego folderu - przeglądarka otworzy plik albo go pobierze; klucz uznaje oba zachowania (R.3.2).

    zawody.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <section id="title">
                <h1>Zawody polskich wędkarzy</h1>
            </section>
            <section id="photo">
                <img src="zawody.jpg" alt="wędkowanie">
            </section>
        </header>
        <main>
            <h3>Łowiska</h3>
            <ul>
                <li>Zalew Węgrowski</li>
                <li>Zbiornik Bukówka</li>
                <li>Jeziorko Bartbetowskie</li>
                <li>Warta-Obrzycko</li>
            </ul>
            <h3>Dodaj zawody wędkarskie</h3>
            <form action="zgloszenie.php" method="post">
                <div>
                    <label for="fishery">Łowisko: </label>
                    <input type="number" id="fishery" name="fishery" min="1" required>
                </div>
                <div>
                    <label for="date">Data: </label>
                    <input type="date" id="date" name="date" required>
                </div>
                <div>
                    <label for="referee">Sędzia: </label>
                    <input type="text" id="referee" name="referee" autocomplete="name" required>
                </div>
                <button type="reset">CZYŚĆ</button>
                <button type="submit">DODAJ</button>
            </form>
        </main>
        <footer>
            <section id="downloads">
                <a href="kwerendy.txt">Pobierz</a>
            </section>
            <section id="author">
            </section>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (zawody.html)
  22. Krok 22: Drugi blok stopki

    Kryteria:

    R.2.5 W bloku lewym zapisano nagłówek h1: „Zawody polskich wędkarzy”, w bloku głównym dwa h3: „Łowiska” i „Dodaj zawody wędkarskie” oraz w drugiej stopce akapit o treści "Stronę przygotował:" z numerem zdającego

    ok. 1 min
    Polecenie z arkusza

    Zawartość drugiego bloku stopki: akapit (paragraf) o treści: „Stronę przygotował: ”, dalej wstawiony numer zdającego, którym został podpisany arkusz.

    Akapit <p> w drugim bloku stopki. Na egzaminie wpisujesz numer, którym podpisany jest arkusz (PESEL); tu stoi autor rozwiązania - „Bartosz Bryniarski”. Strona ma już <h1>, dwa <h3> i akapit w drugiej stopce (R.2.5).

    zawody.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <section id="title">
                <h1>Zawody polskich wędkarzy</h1>
            </section>
            <section id="photo">
                <img src="zawody.jpg" alt="wędkowanie">
            </section>
        </header>
        <main>
            <h3>Łowiska</h3>
            <ul>
                <li>Zalew Węgrowski</li>
                <li>Zbiornik Bukówka</li>
                <li>Jeziorko Bartbetowskie</li>
                <li>Warta-Obrzycko</li>
            </ul>
            <h3>Dodaj zawody wędkarskie</h3>
            <form action="zgloszenie.php" method="post">
                <div>
                    <label for="fishery">Łowisko: </label>
                    <input type="number" id="fishery" name="fishery" min="1" required>
                </div>
                <div>
                    <label for="date">Data: </label>
                    <input type="date" id="date" name="date" required>
                </div>
                <div>
                    <label for="referee">Sędzia: </label>
                    <input type="text" id="referee" name="referee" autocomplete="name" required>
                </div>
                <button type="reset">CZYŚĆ</button>
                <button type="submit">DODAJ</button>
            </form>
        </main>
        <footer>
            <section id="downloads">
                <a href="kwerendy.txt">Pobierz</a>
            </section>
            <section id="author">
                <p>Stronę przygotował: Bartosz Bryniarski</p>
            </section>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (zawody.html)
  23. Etap 3: Styl CSS

    Kroki 23-30 · po tym etapie masz 30 z 35 kryteriów (pkt)

    Krok 23: Plik styl3.css: zmienne i krój czcionki

    Kryteria:

    R.4.1 Ustawiono domyślne formatowanie wszystkich selektorów (*): krój czcionki Verdana (w przypadku wymienionych kilku czcionek Verdana jest wymieniona jako pierwsza)

    ok. 2 min
    Polecenie z arkusza

    Domyślne formatowanie wszystkich selektorów: krój czcionki Verdana

    Dwa kolory z arkusza w zmiennych - SeaGreen pojawi się w trzech regułach (bloki górne, stopki, odnośnik), MintCream w dwóch. Selektor uniwersalny * z Verdaną na pierwszym miejscu (R.4.1) - krój dostają wszystkie elementy, także pola i przyciski formularza; sans-serif to krój zapasowy.

    styl3.css CSS nowy plik
    :root {
        --green: SeaGreen;
        --mint: MintCream;
    }
    
    * {
        font-family: Verdana, sans-serif;
    }
    Podgląd strony po tym kroku (zawody.html)
  24. Krok 24: Bloki lewy i prawy

    ok. 2 min
    Polecenie z arkusza

    Wspólne dla bloku lewego i prawego: kolor tła SeaGreen, biały kolor czcionki, interlinia 150 px, wysokość 260 px, rozmiar czcionki 160%. Dodatkowo dla bloku lewego: szerokość 75%. Dodatkowo dla bloku prawego: szerokość 25%, wyrównanie tekstu do prawej strony

    Wspólna reguła dla obu bloków i osobna dla prawego. Interlinia to line-height - przy 150 px nagłówek stoi wyraźnie niżej niż przy górnej krawędzi, jak na obrazie 2. text-align: right działa też na obraz, bo <img> jest elementem liniowym - zdjęcie dosuwa się do prawej krawędzi.

    Szerokości 75% i 25% tu nie ma: w siatce procent przy bloku liczyłby się od jego kolumny, więc trafią do definicji kolumn siatki - klucz R.4.4 wprost to dopuszcza.

    styl3.css CSS zmienione: 13 linii
    :root {
        --green: SeaGreen;
        --mint: MintCream;
    }
    
    * {
        font-family: Verdana, sans-serif;
    }
    
    #title,
    #photo {
        background-color: var(--green);
        color: white;
        line-height: 150px;
        height: 260px;
        font-size: 160%;
    }
    
    #photo {
        text-align: right;
    }
    Podgląd strony po tym kroku (zawody.html)
  25. Krok 25: Blok główny

    ok. 1 min
    Polecenie z arkusza

    Dla bloku głównego: kolor tła MintCream, marginesy wewnętrzne 80 px

    Selektor znacznika main; padding: 80px z każdej strony - stąd duże odstępy wokół listy i formularza na obrazie 2.

    styl3.css CSS zmienione: 5 linii
    :root {
        --green: SeaGreen;
        --mint: MintCream;
    }
    
    * {
        font-family: Verdana, sans-serif;
    }
    
    #title,
    #photo {
        background-color: var(--green);
        color: white;
        line-height: 150px;
        height: 260px;
        font-size: 160%;
    }
    
    #photo {
        text-align: right;
    }
    
    main {
        background-color: var(--mint);
        padding: 80px;
    }
    Podgląd strony po tym kroku (zawody.html)
  26. Krok 26: Oba bloki stopki

    Kryteria: ,

    R.4.5 Ustawiono wysokość dla bloku lewego i prawego 260px oraz dla obu bloków stopki 70px

    R.4.8 Ustawiono wyrównanie tekstu do prawej strony dla bloku prawego, do środka dla obu bloków stopki oraz ustawiono rozmiar czcionki 160% dla bloków lewego i prawego

    ok. 1 min
    Polecenie z arkusza

    Wspólne dla obu stopek: kolor tła SeaGreen, biały kolor czcionki, szerokość 50%, wysokość 70 px, wyrównanie tekstu do środka

    Jedna reguła dla obu bloków stopki; szerokość 50%, jak przy blokach górnych, w kolumnach siatki. Ustawione są już wysokości (R.4.5) oraz wyrównania tekstu z rozmiarem czcionki (R.4.8).

    styl3.css CSS zmienione: 8 linii
    :root {
        --green: SeaGreen;
        --mint: MintCream;
    }
    
    * {
        font-family: Verdana, sans-serif;
    }
    
    #title,
    #photo {
        background-color: var(--green);
        color: white;
        line-height: 150px;
        height: 260px;
        font-size: 160%;
    }
    
    #photo {
        text-align: right;
    }
    
    main {
        background-color: var(--mint);
        padding: 80px;
    }
    
    #downloads,
    #author {
        background-color: var(--green);
        color: white;
        height: 70px;
        text-align: center;
    }
    Podgląd strony po tym kroku (zawody.html)
  27. Krok 27: Kontrolki formularza

    ok. 1 min
    Polecenie z arkusza

    Dla selektora kontrolki (przyciski i pola edycyjne): margines zewnętrzny dolny 20 px

    Pola są znacznikami input, a przyciski - button, więc reguła ma dwa selektory znaczników (uwaga arkusza wyklucza klasy). Margines zewnętrzny dolny to margin-bottom.

    Typowe błędy

    Sam selektor input nie obejmie przycisków <button> - wersja podstawowa ma przyciski <input type="reset"> i <input type="submit">, więc tam jeden selektor wystarcza.

    styl3.css CSS zmienione: 5 linii
    :root {
        --green: SeaGreen;
        --mint: MintCream;
    }
    
    * {
        font-family: Verdana, sans-serif;
    }
    
    #title,
    #photo {
        background-color: var(--green);
        color: white;
        line-height: 150px;
        height: 260px;
        font-size: 160%;
    }
    
    #photo {
        text-align: right;
    }
    
    main {
        background-color: var(--mint);
        padding: 80px;
    }
    
    #downloads,
    #author {
        background-color: var(--green);
        color: white;
        height: 70px;
        text-align: center;
    }
    
    input,
    button {
        margin-bottom: 20px;
    }
    Podgląd strony po tym kroku (zawody.html)
  28. Krok 28: Cień obrazu

    Kryteria:

    R.4.9 Ustawiono cień dla selektora img o wartości box-shadow: 15px 15px 10px DimGray

    ok. 1 min
    Polecenie z arkusza

    Dla selektora obrazu: cień o przesunięciu 15 px w obu osiach, rozmyciu 10 px i kolorze DimGray

    box-shadow w kolejności ze składni podanej w arkuszu: przesunięcie poziome, pionowe, rozmycie, kolor. Dodatnie przesunięcia kładą cień w prawo i w dół. Selektor znacznika img (R.4.9).

    styl3.css CSS zmienione: 4 linie
    :root {
        --green: SeaGreen;
        --mint: MintCream;
    }
    
    * {
        font-family: Verdana, sans-serif;
    }
    
    #title,
    #photo {
        background-color: var(--green);
        color: white;
        line-height: 150px;
        height: 260px;
        font-size: 160%;
    }
    
    #photo {
        text-align: right;
    }
    
    main {
        background-color: var(--mint);
        padding: 80px;
    }
    
    #downloads,
    #author {
        background-color: var(--green);
        color: white;
        height: 70px;
        text-align: center;
    }
    
    input,
    button {
        margin-bottom: 20px;
    }
    
    img {
        box-shadow: 15px 15px 10px DimGray;
    }
    Podgląd strony po tym kroku (zawody.html)
  29. Krok 29: Odnośnik

    Kryteria: , , , ,

    R.4.2 Ustawiono kolor tła SeaGreen dla bloków lewego, prawego i obu bloków stopki oraz MintCream dla bloku głównego i selektora a

    R.4.3 Ustawiono biały kolor czcionki dla bloków lewego, prawego i obu bloków stopki oraz SeaGreen dla odnośnika

    R.4.6 Ustawiono interlinię dla bloku lewego i prawego: 150px oraz 70px dla odnośnika

    R.4.7 Ustawiono marginesy wewnętrzne (padding) 80px dla bloku głównego, 15px dla odnośnika oraz ustawiono margin-bottom: 20px dla wszystkich kontrolek

    R.4.10 Ustawiono brak podkreślenia dla odnośnika

    ok. 2 min
    Polecenie z arkusza

    Dla selektora odnośnika: brak podkreślenia, kolor tła MintCream, kolor czcionki SeaGreen, marginesy wewnętrzne 15 px, interlinia 70 px

    Selektor znacznika a. Brak podkreślenia to text-decoration: none. Interlinia 70 px równa wysokości stopki stawia napis w pionie na środku, a jasne tło z marginesem wewnętrznym robi z odnośnika „przycisk”, jak na obrazie 2. Ustawione są już wszystkie kolory (R.4.2, R.4.3), interlinie (R.4.6), marginesy (R.4.7) i brak podkreślenia (R.4.10).

    styl3.css CSS zmienione: 8 linii
    :root {
        --green: SeaGreen;
        --mint: MintCream;
    }
    
    * {
        font-family: Verdana, sans-serif;
    }
    
    #title,
    #photo {
        background-color: var(--green);
        color: white;
        line-height: 150px;
        height: 260px;
        font-size: 160%;
    }
    
    #photo {
        text-align: right;
    }
    
    main {
        background-color: var(--mint);
        padding: 80px;
    }
    
    #downloads,
    #author {
        background-color: var(--green);
        color: white;
        height: 70px;
        text-align: center;
    }
    
    input,
    button {
        margin-bottom: 20px;
    }
    
    img {
        box-shadow: 15px 15px 10px DimGray;
    }
    
    a {
        text-decoration: none;
        background-color: var(--mint);
        color: var(--green);
        padding: 15px;
        line-height: 70px;
    }
    Podgląd strony po tym kroku (zawody.html)
  30. Krok 30: Układ bloków: dwie siatki

    Kryteria: ,

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z obrazem 2 w arkuszu (prawidłowo zastosowano właściwości CSS układające bloki na stronie, np. float i clear albo display flex albo grid)

    R.4.4 Ustawiono szerokość bloku lewego 75%, prawego 25%, obu bloków stopki 50% (width lub grid-template-columns lub flex)

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: na górze dwa bloki: lewy i prawy, poniżej blok główny, na dole dwa bloki stopki. Podział zrealizowany za pomocą znaczników sekcji tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z obrazem 2

    • display: grid na <header> i <footer> - każdy pas układa swoje dwa bloki w kolumny,
    • grid-template-columns: 75% 25% w nagłówku i 50% 50% w stopce - szerokości z arkusza (R.4.4).

    <main> jest zwykłym blokiem między dwoma pasami, więc stoi pod blokami górnymi sam z siebie - bez float nie ma clear, a margines wewnętrzny 80 px liczy się od dolnej krawędzi bloków górnych, jak na obrazie 2 (R.3.1).

    Typowe błędy

    width: 75% przy bloku w siatce liczy się od kolumny: blok miałby 75% z 75% strony - szerokości podaje się w grid-template-columns.

    styl3.css CSS zmienione: 13 linii
    :root {
        --green: SeaGreen;
        --mint: MintCream;
    }
    
    * {
        font-family: Verdana, sans-serif;
    }
    
    #title,
    #photo {
        background-color: var(--green);
        color: white;
        line-height: 150px;
        height: 260px;
        font-size: 160%;
    }
    
    #photo {
        text-align: right;
    }
    
    main {
        background-color: var(--mint);
        padding: 80px;
    }
    
    #downloads,
    #author {
        background-color: var(--green);
        color: white;
        height: 70px;
        text-align: center;
    }
    
    input,
    button {
        margin-bottom: 20px;
    }
    
    img {
        box-shadow: 15px 15px 10px DimGray;
    }
    
    a {
        text-decoration: none;
        background-color: var(--mint);
        color: var(--green);
        padding: 15px;
        line-height: 70px;
    }
    
    header,
    footer {
        display: grid;
    }
    
    header {
        grid-template-columns: 75% 25%;
    }
    
    footer {
        grid-template-columns: 50% 50%;
    }
    Podgląd strony po tym kroku (zawody.html)
  31. Etap 4: Skrypt PHP

    Kroki 31-35 · po tym etapie masz 35 z 35 kryteriów (pkt)

    Krok 31: Plik zgloszenie.php: połączenie z bazą i zamknięcie

    Kryteria: ,

    R.5.1 Skrypt zawiera działające połączenie z serwerem bazy danych i wybór bazy wedkarstwo

    R.5.2 Ostatnią operacją na bazie jest jej zamknięcie (zgodne ze składnią)

    ok. 4 min
    Polecenie z arkusza

    Wymagania dotyczące skryptu: Napisany w języku PHP, w pliku zgloszenie.php. Skrypt łączy się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie wedkarstwo. Na końcu działania skrypt zamyka połączenie z serwerem.

    zgloszenie.php w tym samym folderze co strona - tam wysyła formularz. Plik ma dwie części: na górze blok PHP, który rozmawia z bazą i przygotowuje komunikat, a pod nim dokument HTML5 z tym samym arkuszem stylów, który komunikat wypisuje (<?= ... ?> to skrót od <?php echo ... ?>) i prowadzi z powrotem do strony zawodów. Arkusz nie każe skryptowi nic wypisywać, ale pusta biała strona nie mówi użytkownikowi, czy zapis się udał.

    • new PDO(...) - serwer localhost, baza wedkarstwo, kodowanie utf8mb4, użytkownik root bez hasła (R.5.1). ERRMODE_EXCEPTION - błąd bazy rzuca wyjątek,
    • $pdo = null - PDO nie ma funkcji „zamknij”: połączenie zamyka się, gdy znika ostatnie odwołanie do obiektu. Kolejne operacje będą dopisywane przed tą linią, więc zostanie ona ostatnią operacją na bazie (R.5.2),
    • try / catch (PDOException ...) - przy awarii bazy użytkownik zobaczy zwykłe zdanie zamiast komunikatu PHP ze szczegółami serwera.

    PDO zamiast mysqli z tabeli 1 - klucz przyjmuje obie biblioteki (uwaga przy R.5). Podgląd: wynik prawdziwego uruchomienia skryptu.

    zgloszenie.php PHP nowy plik
    <?php
    $message = '';
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=wedkarstwo;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $message = 'Połączenie z bazą działa.';
        $pdo = null;    // zamknięcie połączenia - ostatnia operacja na bazie
    } catch (PDOException $exception) {
        $message = 'Nie udało się zapisać zawodów. Spróbuj ponownie za chwilę.';
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <main>
            <h3>Dodaj zawody wędkarskie</h3>
            <p><?= $message ?></p>
            <p><a href="zawody.html">Wróć do strony zawodów</a></p>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (zgloszenie.php)
  32. Krok 32: Skrypt: dane z formularza i ich sprawdzenie

    Kryteria:

    R.5.4 Skrypt pobiera dane z tablicy globalnej odpowiadającej zastosowanej metodzie formularza ($_POST, $_GET, $_REQUEST)

    ok. 4 min
    Polecenie z arkusza

    Skrypt działa na danych przesłanych z formularza

    Formularz wysyła dane metodą POST, więc skrypt czyta je z tablicy $_POST - kluczami są nazwy z atrybutów name: fishery, date, referee (R.5.4). Zanim cokolwiek trafi do bazy, dane są sprawdzane:

    • ?? '' - gdy pola nie ma (np. plik otwarty wprost z paska adresu), zmienna dostaje pusty napis zamiast ostrzeżenia „Undefined array key”,
    • łowisko: filter_var z FILTER_VALIDATE_INT i min_range 1 zwraca liczbę całkowitą albo false (dla 0, -3, 2.5, pustego pola),
    • data: DateTime::createFromFormat('!Y-m-d', ...) i porównanie z powrotem z tym samym formatem - odpada pusty napis i daty, których nie ma (2021-02-30 PHP po cichu zamieniłby na 2 marca),
    • sędzia: trim obcina spacje z brzegów, więc same spacje to puste pole.

    Błędy trafiają do listy $errors, a połączenie z bazą powstaje tylko dla poprawnych danych. Sprawdzone na prawdziwym PHP: łowisko 0, data 2021-02-30 i sędzia ze spacji dają trzy komunikaty.

    Typowe błędy

    Klucz R.5.4 wymaga odczytu z tablicy globalnej ($_POST), dlatego nie ma tu filter_input. Wpisanie $_POST['lowisko'] przy polu name="fishery" daje pustą wartość - klucz w $_POST to dokładnie name pola.

    zgloszenie.php PHP zmienione: 32 linie
    <?php
    // dane z formularza i ich sprawdzenie
    $fishery = filter_var($_POST['fishery'] ?? '', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]);
    $date = $_POST['date'] ?? '';
    $referee = trim($_POST['referee'] ?? '');
    
    $errors = [];
    $parsedDate = DateTime::createFromFormat('!Y-m-d', $date);
    if ($fishery === false) {
        $errors[] = 'Podaj numer łowiska - liczbę całkowitą od 1.';
    }
    if ($parsedDate === false || $parsedDate->format('Y-m-d') !== $date) {
        $errors[] = 'Wybierz datę zawodów.';
    }
    if ($referee === '') {
        $errors[] = 'Podaj sędziego.';
    }
    
    $message = 'Zawody nie zostały dodane.';
    if ($errors === []) {
        try {
            $pdo = new PDO('mysql:host=localhost;dbname=wedkarstwo;charset=utf8mb4', 'root', '', [
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            ]);
    
            $message = 'Dane z formularza są poprawne.';
            $pdo = null;    // zamknięcie połączenia - ostatnia operacja na bazie
        } catch (PDOException $exception) {
            $message = 'Nie udało się zapisać zawodów. Spróbuj ponownie za chwilę.';
        }
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <main>
            <h3>Dodaj zawody wędkarskie</h3>
            <p><?= $message ?></p>
    <?php foreach ($errors as $error): ?>
            <p role="alert"><?= $error ?></p>
    <?php endforeach; ?>
            <p><a href="zawody.html">Wróć do strony zawodów</a></p>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (zgloszenie.php)
  33. Krok 33: Skrypt: sprawdzenie łowiska i zapytanie przygotowane

    Kryteria: ,

    R.5.3 Skrypt wysyła do bazy danych zmodyfikowane zapytanie 1, tak że w odpowiednich polach są wpisane dane pobrane z formularza

    R.5.5 Skrypt dodaje rekord w tabeli zawody_wedkarskie - sprawdzić w phpMyAdmin

    ok. 5 min
    Polecenie z arkusza

    Wysyła do bazy danych zapytanie 1, które w polu Karty_wedkarskie_id zawiera wartość 0, pozostałe wartości wypełnione są danymi z formularza

    Najpierw skrypt pyta bazę, czy takie łowisko istnieje: SELECT akwen FROM lowisko WHERE id = :id i fetchColumn() - nazwa akwenu albo false. W bazie z arkusza nie ma kluczy obcych, więc bez tego sprawdzenia INSERT przyjąłby łowisko numer 9, którego nie ma.

    Potem zapytanie 1 z danymi z formularza (R.5.3): lista kolumn bez id, 0 w polu Karty_wedkarskie_id (zwycięzca jeszcze nieznany - tak każe arkusz), a w miejscu wartości parametry :fishery, :date, :referee. prepare wysyła do bazy samą treść zapytania, execute([...]) - osobno dane, więc apostrof w nazwisku (Piotr O'Neill) zapisuje się poprawnie i nie zmienia zapytania. Po zapisie $statement = null i $pdo = null zamykają połączenie.

    Sprawdzone na prawdziwej bazie (obok tabela w phpMyAdmin): po wysłaniu formularza z łowiskiem 4, datą 2021-10-02 i sędzią Janem Kowalewskim tabela ma nowy wiersz 5 - 0, 4, 2021-10-02, Jan Kowalewski (R.5.5).

    ⚠️ Sprzeczność w arkuszu: wartość 0 nie wskazuje żadnego wędkarza (karty mają numery 1 i 2). Baza ją przyjmuje tylko dlatego, że w pliku baza.sql nie ma kluczy obcych, choć obraz 1 oznacza pola jako FK. Arkusz i klucz CKE wymagają 0 - na egzaminie punkt daje wartość z klucza.

    Typowe błędy

    Tabela zawody_wedkarskie jest w latin1: sędzia z polską literą, np. „Łukasz Żak”, zapisze się jako „?ukasz ?ak” - bez wyjątku, tylko z ostrzeżeniem w bazie (sprawdzone). Testując formularz, wpisz sędziego bez polskich liter, jak „Jan Kowalewski” z bazy. Poza egzaminem tabelę przestawia się na utf8mb4 (ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4).

    zgloszenie.php PHP zmienione: 17 linii
    <?php
    // dane z formularza i ich sprawdzenie
    $fishery = filter_var($_POST['fishery'] ?? '', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]);
    $date = $_POST['date'] ?? '';
    $referee = trim($_POST['referee'] ?? '');
    
    $errors = [];
    $parsedDate = DateTime::createFromFormat('!Y-m-d', $date);
    if ($fishery === false) {
        $errors[] = 'Podaj numer łowiska - liczbę całkowitą od 1.';
    }
    if ($parsedDate === false || $parsedDate->format('Y-m-d') !== $date) {
        $errors[] = 'Wybierz datę zawodów.';
    }
    if ($referee === '') {
        $errors[] = 'Podaj sędziego.';
    }
    
    $message = 'Zawody nie zostały dodane.';
    $saved = false;
    if ($errors === []) {
        try {
            $pdo = new PDO('mysql:host=localhost;dbname=wedkarstwo;charset=utf8mb4', 'root', '', [
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            ]);
    
            $statement = $pdo->prepare('SELECT akwen FROM lowisko WHERE id = :id');
            $statement->execute(['id' => $fishery]);
            $fisheryName = $statement->fetchColumn();
            if ($fisheryName === false) {
                $message = 'Nie ma łowiska o numerze ' . $fishery . '.';
            } else {
                // zapytanie 1: Karty_wedkarskie_id = 0 (zwycięzca jeszcze nieznany - tak każe arkusz)
                $statement = $pdo->prepare(
                    'INSERT INTO zawody_wedkarskie (Karty_wedkarskie_id, Lowisko_id, data_zawodow, sedzia)
                     VALUES (0, :fishery, :date, :referee)'
                );
                $statement->execute(['fishery' => $fishery, 'date' => $date, 'referee' => $referee]);
                $saved = true;
                $message = 'Zawody zostały dodane.';
            }
            $statement = null;
            $pdo = null;    // zamknięcie połączenia - ostatnia operacja na bazie
        } catch (PDOException $exception) {
            $message = 'Nie udało się zapisać zawodów. Spróbuj ponownie za chwilę.';
        }
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <main>
            <h3>Dodaj zawody wędkarskie</h3>
            <p><?= $message ?></p>
    <?php foreach ($errors as $error): ?>
            <p role="alert"><?= $error ?></p>
    <?php endforeach; ?>
            <p><a href="zawody.html">Wróć do strony zawodów</a></p>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (zgloszenie.php)
    Podgląd strony po kroku 33
  34. Krok 34: Podsumowanie zgłoszenia i bezpieczne wypisywanie

    ok. 2 min

    Dodatek spoza arkusza - klucz go nie ocenia. Po zapisie skrypt pokazuje, co dopisał: nazwę łowiska (z zapytania sprawdzającego - użytkownik widzi, że numer 4 to Warta-Obrzycko), datę w znaczniku <time> i sędziego. To dane od użytkownika i z bazy, więc przechodzą przez funkcję e() z góry pliku - htmlspecialchars z ENT_QUOTES zamienia <, >, & i cudzysłowy na encje: znacznik wpisany w pole „Sędzia” pokaże się jako tekst, a nie wykona na stronie. Przez e() idą też komunikat i błędy - jedna zasada dla wszystkiego, co wypisujesz.

    zgloszenie.php PHP zmienione: 14 linii
    <?php
    function e(string|int|float|null $value): string
    {
        return htmlspecialchars((string) $value, ENT_QUOTES);
    }
    
    // dane z formularza i ich sprawdzenie
    $fishery = filter_var($_POST['fishery'] ?? '', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]);
    $date = $_POST['date'] ?? '';
    $referee = trim($_POST['referee'] ?? '');
    
    $errors = [];
    $parsedDate = DateTime::createFromFormat('!Y-m-d', $date);
    if ($fishery === false) {
        $errors[] = 'Podaj numer łowiska - liczbę całkowitą od 1.';
    }
    if ($parsedDate === false || $parsedDate->format('Y-m-d') !== $date) {
        $errors[] = 'Wybierz datę zawodów.';
    }
    if ($referee === '') {
        $errors[] = 'Podaj sędziego.';
    }
    
    $message = 'Zawody nie zostały dodane.';
    $saved = false;
    if ($errors === []) {
        try {
            $pdo = new PDO('mysql:host=localhost;dbname=wedkarstwo;charset=utf8mb4', 'root', '', [
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            ]);
    
            $statement = $pdo->prepare('SELECT akwen FROM lowisko WHERE id = :id');
            $statement->execute(['id' => $fishery]);
            $fisheryName = $statement->fetchColumn();
            if ($fisheryName === false) {
                $message = 'Nie ma łowiska o numerze ' . $fishery . '.';
            } else {
                // zapytanie 1: Karty_wedkarskie_id = 0 (zwycięzca jeszcze nieznany - tak każe arkusz)
                $statement = $pdo->prepare(
                    'INSERT INTO zawody_wedkarskie (Karty_wedkarskie_id, Lowisko_id, data_zawodow, sedzia)
                     VALUES (0, :fishery, :date, :referee)'
                );
                $statement->execute(['fishery' => $fishery, 'date' => $date, 'referee' => $referee]);
                $saved = true;
                $message = 'Zawody zostały dodane.';
            }
            $statement = null;
            $pdo = null;    // zamknięcie połączenia - ostatnia operacja na bazie
        } catch (PDOException $exception) {
            $message = 'Nie udało się zapisać zawodów. Spróbuj ponownie za chwilę.';
        }
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <main>
            <h3>Dodaj zawody wędkarskie</h3>
            <p><?= e($message) ?></p>
    <?php if ($saved): ?>
            <ul>
                <li>Łowisko: <?= e($fisheryName) ?></li>
                <li>Data: <time datetime="<?= e($date) ?>"><?= e($date) ?></time></li>
                <li>Sędzia: <?= e($referee) ?></li>
            </ul>
    <?php endif; ?>
    <?php foreach ($errors as $error): ?>
            <p role="alert"><?= e($error) ?></p>
    <?php endforeach; ?>
            <p><a href="zawody.html">Wróć do strony zawodów</a></p>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (zgloszenie.php)
  35. Krok 35: Odświeżenie nie dodaje zawodów drugi raz (PRG)

    ok. 4 min

    Dodatek spoza arkusza - klucz go nie ocenia. Strona z komunikatem jest wynikiem żądania POST: odświeżenie (F5) wysyła formularz jeszcze raz i w tabeli są dwa takie same zawody. Wzorzec PRG (Post/Redirect/Get) to usuwa:

    • session_start() na samym początku pliku - sesja przechowa dane między dwoma żądaniami,
    • obsługa formularza stoi w if ($_SERVER['REQUEST_METHOD'] === 'POST'). Po udanym zapisie ($saved) skrypt - już po zamknięciu połączenia - wkłada dane do $_SESSION i wysyła header('Location: zgloszenie.php'), a potem exit - header tylko ustawia nagłówek odpowiedzi i nie zatrzymuje skryptu,
    • przeglądarka wczytuje plik jeszcze raz, zwykłym żądaniem GET. Gałąź elseif odczytuje dane z sesji, od razu je usuwa i pokazuje podsumowanie; kolejne odświeżenie zostawia już tylko zdanie z odnośnikiem do formularza.

    Sprawdzone na prawdziwym PHP: przekierowanie 302, podsumowanie po nim, odświeżenie bez drugiego wiersza w tabeli, łowisko 9, sędzia <b>Jan</b> (wypisany jako tekst) i złe hasło do bazy - za każdym razem bez ostrzeżeń PHP.

    Typowe błędy

    header('Location: ...') po wypisaniu choćby jednego znaku (także pustej linii przed <?php) nie zadziała - nagłówki muszą wyjść przed treścią strony.

    zgloszenie.php PHP zmienione: 58 linii
    <?php
    session_start();
    
    function e(string|int|float|null $value): string
    {
        return htmlspecialchars((string) $value, ENT_QUOTES);
    }
    
    $errors = [];
    $saved = false;
    $message = 'Formularz zgłoszenia jest na stronie zawodów.';
    
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        // dane z formularza i ich sprawdzenie
        $fishery = filter_var($_POST['fishery'] ?? '', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]);
        $date = $_POST['date'] ?? '';
        $referee = trim($_POST['referee'] ?? '');
    
        $parsedDate = DateTime::createFromFormat('!Y-m-d', $date);
        if ($fishery === false) {
            $errors[] = 'Podaj numer łowiska - liczbę całkowitą od 1.';
        }
        if ($parsedDate === false || $parsedDate->format('Y-m-d') !== $date) {
            $errors[] = 'Wybierz datę zawodów.';
        }
        if ($referee === '') {
            $errors[] = 'Podaj sędziego.';
        }
    
        $message = 'Zawody nie zostały dodane.';
        if ($errors === []) {
            try {
                $pdo = new PDO('mysql:host=localhost;dbname=wedkarstwo;charset=utf8mb4', 'root', '', [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                ]);
                $statement = $pdo->prepare('SELECT akwen FROM lowisko WHERE id = :id');
                $statement->execute(['id' => $fishery]);
                $fisheryName = $statement->fetchColumn();
                if ($fisheryName === false) {
                    $message = 'Nie ma łowiska o numerze ' . $fishery . '.';
                } else {
                    // zapytanie 1: Karty_wedkarskie_id = 0 (zwycięzca jeszcze nieznany - tak każe arkusz)
                    $statement = $pdo->prepare(
                        'INSERT INTO zawody_wedkarskie (Karty_wedkarskie_id, Lowisko_id, data_zawodow, sedzia)
                         VALUES (0, :fishery, :date, :referee)'
                    );
                    $statement->execute(['fishery' => $fishery, 'date' => $date, 'referee' => $referee]);
                    $saved = true;
                    $message = 'Zawody zostały dodane.';
                }
                $statement = null;
                $pdo = null;    // zamknięcie połączenia - ostatnia operacja na bazie
                if ($saved) {
                    // PRG: dane do sesji i przekierowanie - odświeżenie nie zapisze zawodów drugi raz
                    $_SESSION['contest'] = ['fishery' => $fisheryName, 'date' => $date, 'referee' => $referee];
                    header('Location: zgloszenie.php');
                    exit;
                }
            } catch (PDOException $exception) {
                $message = 'Nie udało się zapisać zawodów. Spróbuj ponownie za chwilę.';
            }
        }
    } elseif (isset($_SESSION['contest'])) {
        // żądanie GET po przekierowaniu: dane z sesji, od razu usunięte
        ['fishery' => $fisheryName, 'date' => $date, 'referee' => $referee] = $_SESSION['contest'];
        unset($_SESSION['contest']);
        $saved = true;
        $message = 'Zawody zostały dodane.';
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Zawody wędkarskie</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <main>
            <h3>Dodaj zawody wędkarskie</h3>
            <p><?= e($message) ?></p>
    <?php if ($saved): ?>
            <ul>
                <li>Łowisko: <?= e($fisheryName) ?></li>
                <li>Data: <time datetime="<?= e($date) ?>"><?= e($date) ?></time></li>
                <li>Sędzia: <?= e($referee) ?></li>
            </ul>
    <?php endif; ?>
    <?php foreach ($errors as $error): ?>
            <p role="alert"><?= e($error) ?></p>
    <?php endforeach; ?>
            <p><a href="zawody.html">Wróć do strony zawodów</a></p>
        </main>
    </body>
    </html>

    Podgląd strony bez zmian - taki jak po kroku 34.

  36. Etap 5: Porównanie z wersją podstawową

    Krok 36 · po tym etapie masz 35 z 35 kryteriów (pkt)

    Krok 36: Co jest inaczej i którą wersję wybrać na egzaminie

    ok. 3 min

    Obie wersje dają komplet 35 punktów. Różnice:

    wersja podstawowawersja nowoczesna
    układfloat: left czterech bloków, clear bloku głównegosiatki w <header> (75% 25%) i <footer> (50% 50%)
    bloki#left, #right, main, dwa <footer>dwie <section> w <header>, main, dwie <section> w <footer>
    kolorywpisane w każdą regułęzmienne CSS
    formularz<br> po polach, <input type="reset/submit">bloki <div>, <button>, min, required
    zapytanie 1VALUES (NULL, ...) w kolejności kolumnlista kolumn bez id
    bibliotekamysqli (tabela 1 arkusza)PDO z wyjątkami
    dane z formularzawklejone do zapytaniasprawdzone (także łowisko w bazie) i podane jako parametry
    wynikpusta stronakomunikat z podsumowaniem przez e()
    odświeżenie po zapisiedodaje zawody drugi razPRG - przekierowanie, dane z sesji

    W prawdziwym projekcie dane logowania do bazy trzyma się zwykle w osobnym pliku (np. config.php), formularz chroni się tokenem CSRF, a tabele mają klucze obce i zestaw znaków utf8mb4 - klucz tego nie wymaga.

    Na egzaminie wersja podstawowa trzyma się funkcji z tabeli 1 arkusza i łatwiej ją napisać bez dokumentacji pod ręką. Nowoczesna jest odporna na błędne i podmienione dane z formularza. Obie biblioteki klucz przyjmuje.

    Podgląd strony bez zmian - taki jak po kroku 34.

  37. Etap 6: Oddanie pracy

    Krok 37 · po tym etapie masz 35 z 35 kryteriów (pkt)

    Krok 37: Plik przeglądarka.txt i nagranie płyty

    ok. 5 min
    Polecenie z arkusza

    Po zakończeniu pracy utwórz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowałeś poprawność działania witryny. Umieść go w folderze z numerem, którym został podpisany arkusz. Nagraj płytę z rezultatami pracy. W folderze z numerem, którym został podpisany arkusz powinny znajdować się pliki: import.png, kw1.jpg, kw2.jpg, kw3.jpg, kw4.jpg, kwerendy.txt, przeglądarka.txt, styl3.css, zawody.html, zawody.jpg, zgloszenie.php, ewentualnie inne przygotowane pliki.

    W przeglądarka.txt nazwa przeglądarki, w której sprawdzana była strona przez http://localhost/.... Sprawdź listę plików (zawody.jpg odbity, 251 × 250 px), nagraj płytę, sprawdź jej odczyt i opisz ją numerem zdającego.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

    Podgląd strony bez zmian - taki jak po kroku 34.

Podgląd

To jedno z możliwych rozwiązań. Egzaminator ocenia spełnienie kryteriów z klucza odpowiedzi, a nie zgodność z tym kodem - inna, poprawna droga też daje punkty.

Autor rozwiązania: . Licencja CC BY-NC 4.0 - kopiowanie i przeróbki do celów niekomercyjnych, z podaniem autora i źródła (link do tej strony) (zasady wykorzystania). Treść arkusza i klucza oceniania pochodzi z CKE.