Przejdź do głównej treści
INF.03-03-23.01-SGStyczeń 2023 · 44 kroki · ok. 73 min · 35 kryteriów z klucza

Rozwiązanie krok po kroku: Witryna kwiaciarni z bazą danych (Wersja podstawowa)

Witryna Grupy Polskich Kwiaciarni to baza kwiaciarnia (kwiaciarnie i zamówienia) z czterema zapytaniami - warunek na tekście, COUNT z GROUP BY, złączenie z warunkiem na dacie i CREATE TABLE z kluczem głównym AUTO_INCREMENT i polem UNSIGNED - trzy zdjęcia kwiatów wykadrowane do kwadratu 250 × 250 oraz dwie strony. index.html ma menu z listą numerowaną, w której trzeci element zawiera listę zagnieżdżoną, i trzy zdjęcia z cieniem; znajdz.php różni się od niej tylko blokiem prawym: formularz wysyła nazwę miasta metodą POST, a skrypt wypisuje kwiaciarnie z tego miasta. W stylach jest pseudoelement ::marker (kolor numerów i punktorów listy).

Kroki idą zdanie po zdaniu za treścią arkusza - przy każdym jest polecenie z arkusza, a kod pokazuje dokładnie te linie, które je spełniają. Skrypt jest najpierw napisany najprościej, funkcjami z tabeli 1 arkusza, a na końcu sprawdzony na prawdziwym wstrzyknięciu SQL i przerobiony na zapytanie przygotowane.

To jest wersja podstawowa. W zakładce „Nowoczesny kod (grid, PDO)” jest drugi sposób rozwiązania tego samego arkusza: siatka CSS z nazwanymi obszarami, menu w znaczniku <nav>, kolory w zmiennych CSS, a wyszukiwanie przez PDO z zapytaniem przygotowanym na górze pliku znajdz.php, z komunikatami dla miasta bez kwiaciarni i dla pustego pola - obie wersje są zgodne z kluczem.

Baza i zdjęcia pochodzą z prawdziwego archiwum zad3 (załącznik do arkusza, hasło w treści zadania). Zapytania i zrzuty są policzone na MariaDB 10.4 - tej samej, która jest w XAMPP. Podgląd znajdz.php od kroków z PHP to wynik prawdziwego uruchomienia kodu w PHP 8.2 (klucz każe sprawdzać w XAMPP 8.1.2 - zachowanie tych funkcji jest w obu wersjach takie samo), po wysłaniu formularza z miastem Warszawa - jak na obrazie 3.

Jak liczą się punkty. Klucz ma 35 kryteriów (R.1.1 - R.5.5), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 27 punktów - można stracić 8 kryteriów i nadal zdać. Przy każdym kroku jest napisane, które kryteria spełnia; egzaminator ocenia spełnienie kryteriów z klucza, nie zgodność z tym kodem.

  1. Etap 1: Baza danych

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

    Krok 1: Baza danych kwiaciarnia

    ok. 2 min
    Polecenie z arkusza

    Utwórz bazę danych o nazwie kwiaciarnia

    Najpierw archiwum zad3.zip z pulpitu (hasło 5T2k@W$2n - wielkość liter ma znaczenie) i folder z numerem zdającego, do którego trafiają kwiaciarnia.sql i trzy zdjęcia PNG. W phpMyAdmin: Nowa, nazwa kwiaciarnia, porównywanie np. utf8_polish_ci.

    Typowe błędy

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

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

    ok. 2 min
    Polecenie z arkusza

    Do bazy kwiaciarnia zaimportuj tabele z pliku kwiaciarnia.sql z rozpakowanego archiwum

    Przy zaznaczonej bazie kwiaciarnia: Import → kwiaciarnia.sql → Wykonaj. Dwie tabele z obrazu 1: kwiaciarnie (Astra w Warszawie i Melisa w Malborku) i zamowienia (6 zamówień z datą, rodzajem kwiatów i ceną). Pole id_kwiaciarni łączy zamówienie z kwiaciarnią.

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

    R.1.1 Wykonano import tabel do bazy danych kwiaciarnia 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, wklejenie do edytora grafiki i 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: kwiaciarnie w Malborku

    Kryteria: ,

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

    R.1.3 Utworzono zapytanie 1 wybierające jedynie pola nazwa i ulica dla kwiaciarni z miasta Malbork. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = "Malbork"; oraz wynik działania udokumentowano zrzutem, na którym są widoczne jedynie dane: Melisa, Konopnickiej

    ok. 1 min
    Polecenie z arkusza

    Zapytanie 1: wybierające jedynie pola nazwa i ulica dla kwiaciarni z miasta Malbork

    • SELECT nazwa, ulica - dwa pola, bez miasta,
    • FROM kwiaciarnie,
    • WHERE miasto = 'Malbork' - tekst w apostrofach.

    Wynik: Melisa, Konopnickiej - jak w kluczu. Z tego zapytania powstanie skrypt: w miejsce „Malbork” stanie miasto z formularza. Zapytania trafiają do kwerendy.txt, zrzut wyniku do kw1.jpg.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = 'Malbork';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: liczba zamówień każdej kwiaciarni

    Kryteria:

    R.1.4 Utworzono zapytanie 2 wybierające jedynie pole id_kwiaciarni oraz liczące liczbę zamówień dla poszczególnych kwiaciarni. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id_kwiaciarni, COUNT(*) FROM zamowienia GROUP BY id_kwiaciarni; (zamiast * możliwe dowolne pole) oraz wynik działania udokumentowano zrzutem, na którym widoczne są jedynie dane: 1, 4; 2, 2

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 2: wybierające jedynie pole id_kwiaciarni oraz liczące liczbę zamówień dla poszczególnych kwiaciarni

    • SELECT id_kwiaciarni, COUNT(*) - identyfikator i liczba wierszy w grupie; alias liczba_zamowien tylko porządkuje nagłówek kolumny (arkusz go nie wymaga),
    • FROM zamowienia - wystarczy tabela zamówień, bo ma id_kwiaciarni,
    • GROUP BY id_kwiaciarni - zamówienia tej samej kwiaciarni zlewają się w jeden wiersz.

    Wynik: 1, 4 oraz 2, 2 - jak w kluczu. Zrzut: kw2.jpg.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = 'Malbork';
    
    -- Zapytanie 2
    SELECT id_kwiaciarni, COUNT(*) AS liczba_zamowien FROM zamowienia GROUP BY id_kwiaciarni;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: zamówienia z 7 stycznia 2017

    Kryteria:

    R.1.5 Utworzono zapytanie 3 wybierające jedynie pola nazwa i miasto z tabeli kwiaciarnie i odpowiadające im pole kwiaty z tabeli zamowienia dla zamówień z dnia 2017.01.07. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa, miasto, kwiaty FROM zamowienia JOIN kwiaciarnie ON zamowienia.id_kwiaciarni = kwiaciarnie.id_kwiaciarni WHERE data="2017.01.07"; (możliwe też INNER JOIN lub porównanie kluczy po WHERE) oraz wynik działania udokumentowano zrzutem, na którym są widoczne jedynie dane: Astra, Warszawa, róża

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie pola nazwa i miasto z tabeli kwiaciarnie i odpowiadające im pole kwiaty z tabeli zamowienia dla zamówień z dnia 7 stycznia 2017. Należy posłużyć się relacją

    • SELECT nazwa, miasto, kwiaty - dwa pola z kwiaciarni i jedno z zamówień,
    • FROM kwiaciarnie JOIN zamowienia - „posłużyć się relacją” to złączenie,
    • ON kwiaciarnie.id_kwiaciarni = zamowienia.id_kwiaciarni - pole ma tę samą nazwę w obu tabelach, więc trzeba podać nazwę tabeli przed kropką,
    • WHERE data = '2017-01-07' - data w formacie bazy: rok, miesiąc, dzień.

    Wynik: Astra, Warszawa, róża - jak w kluczu. Zrzut: kw3.jpg.

    Typowe błędy

    WHERE data = 7-01-2017 bez apostrofów to odejmowanie liczb, a nie data - zapytanie zwróci pusty wynik.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = 'Malbork';
    
    -- Zapytanie 2
    SELECT id_kwiaciarni, COUNT(*) AS liczba_zamowien FROM zamowienia GROUP BY id_kwiaciarni;
    
    -- Zapytanie 3
    SELECT nazwa, miasto, kwiaty FROM kwiaciarnie JOIN zamowienia ON kwiaciarnie.id_kwiaciarni = zamowienia.id_kwiaciarni WHERE data = '2017-01-07';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: tabela klienci

    Kryteria:

    R.1.6 Utworzono zapytanie 4 tworzące nową tabelę klienci o polach: id, klucz główny, NOT NULL AUTO_INCREMENT; imie i nazwisko, typu tekstowego o długości 15 znaków każde; rabat, przyjmujące jedynie liczby naturalne. W pliku z kwerendami lub na zrzucie istnieje zapis np.: CREATE TABLE klienci ( id int NOT NULL AUTO_INCREMENT, imie varchar(15), nazwisko varchar(15), rabat int UNSIGNED, PRIMARY KEY (id) ); (lub id int NOT NULL AUTO_INCREMENT PRIMARY KEY, dodatkowo id i rabat- dowolny typ całkowity; rabat - wymagane UNSIGNED) oraz wynik działania udokumentowano zrzutem na którym widnieje komunikat o poprawnym utworzeniu tabeli lub poprawna struktura tabeli

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 4: tworzące nową tabelę klienci o polach: id, klucz główny, automatycznie inkrementowany, nie może przyjmować wartości NULL; imie, typu tekstowego o długości 15 znaków; nazwisko, typu tekstowego o długości 15 znaków; rabat, przyjmujący jedynie liczby naturalne

    • CREATE TABLE klienci ( - nowa tabela, w nawiasie lista pól po przecinku,
    • id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY - liczba całkowita, bez wartości pustej, numerowana automatycznie, klucz główny,
    • imie VARCHAR(15), nazwisko VARCHAR(15) - tekst o długości do 15 znaków,
    • rabat INT UNSIGNED - UNSIGNED (bez znaku) dopuszcza tylko liczby nieujemne; klucz wymaga go wprost.

    Struktura po wykonaniu (DESCRIBE klienci) zgadza się z arkuszem. Sprawdzone też, co robi UNSIGNED przy ustawieniach serwera z XAMPP: próba zapisania rabatu −5 zapisuje 0 z ostrzeżeniem. Zrzut kw4.jpg pokazuje komunikat i strukturę tabeli.

    Typowe błędy

    Bez UNSIGNED przy polu rabat klucz nie uzna zapytania - samo INT przyjmuje liczby ujemne.

    kwerendy.txt Tekst zmienione: 8 linii
    -- Zapytanie 1
    SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = 'Malbork';
    
    -- Zapytanie 2
    SELECT id_kwiaciarni, COUNT(*) AS liczba_zamowien FROM zamowienia GROUP BY id_kwiaciarni;
    
    -- Zapytanie 3
    SELECT nazwa, miasto, kwiaty FROM kwiaciarnie JOIN zamowienia ON kwiaciarnie.id_kwiaciarni = zamowienia.id_kwiaciarni WHERE data = '2017-01-07';
    
    -- Zapytanie 4
    CREATE TABLE klienci (
      id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
      imie VARCHAR(15),
      nazwisko VARCHAR(15),
      rabat INT UNSIGNED
    );
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Grafika i strony HTML

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

    Krok 8: Zdjęcia kwiatów: kwadrat 250 × 250, JPEG

    Kryteria:

    R.2.1 Przynajmniej jeden z obrazów z roza , gerbera , gozdzik zachowuje proporcje 1:1, rozmiar 250 px i nie jest rozciągnięty w pionie lub poziomie oraz jest formatu JPEG

    ok. 5 min
    Polecenie z arkusza

    Obrazy roza.png, gerbera.png, gozdzik.png należy przyciąć (wykadrować) do proporcji 1:1 do rozmiaru 250 px na 250 px i zapisać w formacie JPEG

    Dla każdego zdjęcia w GIMP-ie: narzędzie Kadrowanie z zaznaczoną opcją Stałe: Proporcje i wartością 1:1, zaznaczenie wysokie na cały obraz i ustawione na środku kwiatu, Enter. Wycięty kwadrat (560 × 560 px dla gerbery, 426 × 426 dla goździka i róży) jest jeszcze za duży, więc Obraz → Skaluj obraz do 250 × 250 - przy kwadracie proporcje się nie zmieniają, więc kwiat nie jest rozciągnięty. Na koniec Plik → Wyeksportuj jako gerbera.jpg (gozdzik.jpg, roza.jpg); JPEG nie ma przezroczystości, więc ewentualne przezroczyste piksele dostają tło.

    Typowe błędy

    Samo Skaluj obraz do 250 × 250 bez kadrowania ściska zdjęcie 640 × 426 w poziomie - klucz wymaga obrazu nierozciągniętego.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Plik index.html w HTML5

    ok. 1 min
    Polecenie z arkusza

    Zapisane w języku HTML 5

    Deklaracja <!DOCTYPE html> i szkielet strony głównej. Najpierw powstaje cała strona index.html; znajdz.php będzie jej kopią z innym blokiem prawym.

    index.html HTML nowy plik
    <!DOCTYPE html>
    <html>
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  10. Krok 10: Kodowanie polskich znaków

    ok. 1 min
    Polecenie z arkusza

    Jawnie zastosowany właściwy standard kodowania polskich znaków

    <meta charset="UTF-8"> jako pierwszy element <head>.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  11. Krok 11: Język strony

    ok. 1 min
    Polecenie z arkusza

    Zadeklarowany język witryny: polski

    Atrybut lang="pl" w znaczniku <html>.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  12. Krok 12: Tytuł strony

    Kryteria:

    R.2.3 Nadano tytuł stronie: "Kwiaty"

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Kwiaty”

    <title> w <head>.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  13. Krok 13: 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 ma pochodzić z tego pliku.

    Typowe błędy

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

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  14. Krok 14: Bloki: baner, lewy, prawy i stopka

    Kryteria:

    R.2.4 Układ strony zdefiniowano dzieląc ją na bloki: baner, lewy, prawy i stopka. Zastosowano znaczniki sekcji

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: na górze blok banera, poniżej obok siebie bloki lewy i prawy, na dole blok 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

    Baner to <header>, stopka <footer>, a dwa bloki - <section> z identyfikatorami left i right (mają różne kolory i szerokości). Obok siebie postawi je arkusz stylów.

    index.html HTML zmienione: 8 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
        </header>
        <section id="left">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  15. Krok 15: Baner: nagłówek pierwszego stopnia

    ok. 1 min
    Polecenie z arkusza

    Zawartość banera: nagłówek pierwszego stopnia o treści „Grupa Polskich Kwiaciarni”

    <h1> w <header>.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  16. Krok 16: Blok lewy: nagłówek Menu

    ok. 1 min
    Polecenie z arkusza

    Nagłówek drugiego stopnia o treści: „Menu”

    <h2> na początku bloku lewego.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  17. Krok 17: Blok lewy: lista numerowana z trzema elementami

    ok. 1 min
    Polecenie z arkusza

    Lista numerowana (uporządkowana) z trzema elementami oraz z zagnieżdżoną listą punktowaną (nieuporządkowaną) z trzema elementami. Zawartość list jest zgodna z obrazem 2.

    Najpierw sama lista numerowana <ol> z trzema elementami <li>. Odnośniki i lista zagnieżdżona dojdą w kolejnych krokach.

    index.html HTML zmienione: 5 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li>Strona główna</li>
                <li>Rozpoznaj kwiaty</li>
                <li>Znajdź kwiaciarnię</li>
            </ol>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  18. Krok 18: Odnośnik „Strona główna”

    ok. 1 min
    Polecenie z arkusza

    „Strona główna” prowadzi do strony index.html

    Tekst elementu listy otoczony znacznikiem <a> - odnośnik stoi wewnątrz <li>, bo element listy jest odnośnikiem, a nie odwrotnie.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li>Rozpoznaj kwiaty</li>
                <li>Znajdź kwiaciarnię</li>
            </ol>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  19. Krok 19: Odnośnik „Rozpoznaj kwiaty” w nowej karcie

    Kryteria:

    R.3.3 Wybranie odnośnika "Rozpoznaj kwiaty" inicjuje otwarcie strony „https://www.kwiaty.pl/” w nowym oknie / karcie przeglądarki

    ok. 1 min
    Polecenie z arkusza

    „Rozpoznaj kwiaty” prowadzi do strony „https://www.kwiaty.pl/”, odnośnik otwiera się w osobnej karcie przeglądarki

    Adres zewnętrzny pisze się w całości, z https://. Atrybut target="_blank" każe przeglądarce otworzyć stronę w nowej karcie, a strona kwiaciarni zostaje otwarta w starej.

    Typowe błędy

    Bez https:// adres www.kwiaty.pl byłby potraktowany jak plik w folderze strony i odnośnik nie zadziała.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li>Znajdź kwiaciarnię</li>
            </ol>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  20. Krok 20: Odnośnik „Znajdź kwiaciarnię”

    Kryteria:

    R.3.2 Po wybraniu odnośnika "Strona główna" otwiera się strona główna oraz po wybraniu odnośnika "Znajdź kwiaciarnię" otwiera się podstrona

    ok. 1 min
    Polecenie z arkusza

    „Znajdź kwiaciarnię” prowadzi do strony znajdz.php i zagnieżdża listę punktowaną z elementami: w Warszawie, w Malborku, w Poznaniu

    Odnośnik do drugiej strony witryny, która powstanie za chwilę. Działają już oba odnośniki wewnętrzne (R.3.2).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a></li>
            </ol>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  21. Krok 21: Lista punktowana zagnieżdżona w trzecim elemencie

    Kryteria:

    R.2.6 W bloku lewym umieszczono listę numerowaną z trzema elementami, zastosowano znaczniki <ol>, <li>, trzeci element <li> zawiera listę punktowaną ze znacznikami <ul>, <li>

    ok. 2 min
    Polecenie z arkusza

    „Znajdź kwiaciarnię” prowadzi do strony znajdz.php i zagnieżdża listę punktowaną z elementami: w Warszawie, w Malborku, w Poznaniu

    Lista zagnieżdżona stoi wewnątrz trzeciego <li>, przed jego znacznikiem zamykającym - dlatego </li> przenosi się do osobnej linii pod </ul>. Lista punktowana to <ul>; przeglądarka sama robi wcięcie i inny punktor. Elementy listy zagnieżdżonej nie są odnośnikami - arkusz tego nie wymaga.

    Typowe błędy

    <ul> postawione między dwoma <li> (poza elementem) to nie jest lista zagnieżdżona - klucz wymaga, żeby trzeci element <li> zawierał listę.

    index.html HTML zmienione: 7 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a>
                    <ul>
                        <li>w Warszawie</li>
                        <li>w Malborku</li>
                        <li>w Poznaniu</li>
                    </ul>
                </li>
            </ol>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  22. Krok 22: Stopka

    ok. 1 min
    Polecenie z arkusza

    Zawartość stopki: paragraf (akapit) o treści: „Stronę opracował:”, dalej wstawiony numer zdającego

    Akapit <p> w <footer>. Na egzaminie w miejscu imienia i nazwiska wpisuje się numer zdającego, czyli PESEL; w tym rozwiązaniu stoi tam „Bartosz Bryniarski”.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a>
                    <ul>
                        <li>w Warszawie</li>
                        <li>w Malborku</li>
                        <li>w Poznaniu</li>
                    </ul>
                </li>
            </ol>
        </section>
        <section id="right">
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  23. Krok 23: index.html, blok prawy: nagłówek

    Kryteria:

    R.2.5 W banerze zapisano nagłówek h1: "Grupa Polskich Kwiaciarni", w bloku lewym h2: "Menu", w bloku prawym h2: "Strona dla miłośników kwiatów" lub "Znajdź kwiaciarnię", paragraf w stopce

    ok. 1 min
    Polecenie z arkusza

    Nagłówek drugiego stopnia o treści: „Strona dla miłośników kwiatów”

    <h2> w bloku prawym. Strona ma już wszystkie nagłówki i akapit w stopce (R.2.5).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a>
                    <ul>
                        <li>w Warszawie</li>
                        <li>w Malborku</li>
                        <li>w Poznaniu</li>
                    </ul>
                </li>
            </ol>
        </section>
        <section id="right">
            <h2>Strona dla miłośników kwiatów</h2>
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  24. Krok 24: index.html, blok prawy: trzy zdjęcia kwiatów

    Kryteria:

    R.2.7 W bloku prawym strony głównej umieszczono trzy obrazy: gerbera, gozdzik, roza z tekstem alternatywnym - nazwa kwiatu

    ok. 1 min
    Polecenie z arkusza

    Obok siebie trzy obrazy z gerberą, goździkiem i różą, z tekstem alternatywnym, który jest nazwą danego kwiatu

    Trzy <img> jeden za drugim - obrazy są elementami w linii, więc stają obok siebie bez żadnych stylów. Tekst alternatywny to nazwa kwiatu z polskimi literami („goździk”, „róża”), choć nazwy plików ich nie mają.

    index.html HTML zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a>
                    <ul>
                        <li>w Warszawie</li>
                        <li>w Malborku</li>
                        <li>w Poznaniu</li>
                    </ul>
                </li>
            </ol>
        </section>
        <section id="right">
            <h2>Strona dla miłośników kwiatów</h2>
            <img src="gerbera.jpg" alt="gerbera">
            <img src="gozdzik.jpg" alt="goździk">
            <img src="roza.jpg" alt="róża">
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  25. Krok 25: znajdz.php: kopia strony z nowym nagłówkiem bloku prawego

    Kryteria:

    R.2.2 Witrynę internetową zapisano w plikach index.html i znajdz.php oraz zapisano jawnie standard kodowania polskich znaków i deklarację HTML5 <!DOCTYPE HTML> i zadeklarowano język witryny: polski np. <html lang="pl">

    ok. 2 min
    Polecenie z arkusza

    Nagłówek drugiego stopnia o treści: „Znajdź kwiaciarnię”

    Strony różnią się tylko blokiem prawym, więc index.html zapisuje się pod nazwą znajdz.php i w bloku prawym zostaje sam nagłówek „Znajdź kwiaciarnię” - zdjęcia znikają. Rozszerzenie .php jest potrzebne, żeby serwer wykonał skrypt; strona działa tylko otwarta przez http://localhost/.... Witryna jest już zapisana w obu plikach, z deklaracją HTML5, kodowaniem i językiem (R.2.2).

    znajdz.php PHP nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a>
                    <ul>
                        <li>w Warszawie</li>
                        <li>w Malborku</li>
                        <li>w Poznaniu</li>
                    </ul>
                </li>
            </ol>
        </section>
        <section id="right">
            <h2>Znajdź kwiaciarnię</h2>
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  26. Krok 26: Formularz wysyłany metodą POST do tej samej strony

    Kryteria:

    R.3.5 Formularz wysyła dane metodą POST do tego samego pliku (poprawne też bez atrybutu action)

    ok. 1 min
    Polecenie z arkusza

    Formularz wysyłający dane metodą bezpieczną do tego samego pliku.

    „Metoda bezpieczna” w rozumieniu arkusza to post - dane jadą w treści żądania, a nie w adresie. W specyfikacji HTTP „bezpieczne” są co prawda metody, które niczego nie zmieniają na serwerze (GET i HEAD), ale arkusz używa tego słowa w innym sensie, a klucz wymaga POST. „Do tego samego pliku” - action="znajdz.php"; klucz uznaje też formularz bez action.

    znajdz.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a>
                    <ul>
                        <li>w Warszawie</li>
                        <li>w Malborku</li>
                        <li>w Poznaniu</li>
                    </ul>
                </li>
            </ol>
        </section>
        <section id="right">
            <h2>Znajdź kwiaciarnię</h2>
            <form method="post" action="znajdz.php">
            </form>
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  27. Krok 27: Pole edycyjne na nazwę miasta

    ok. 1 min
    Polecenie z arkusza

    Pole edycyjne poprzedzone napisem „Podaj nazwę miasta:”

    <input type="text"> z nazwą city - pod tą nazwą wartość trafi do PHP. Napis i pole są w jednym <label>.

    znajdz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a>
                    <ul>
                        <li>w Warszawie</li>
                        <li>w Malborku</li>
                        <li>w Poznaniu</li>
                    </ul>
                </li>
            </ol>
        </section>
        <section id="right">
            <h2>Znajdź kwiaciarnię</h2>
            <form method="post" action="znajdz.php">
                <label>Podaj nazwę miasta: <input type="text" name="city"></label>
            </form>
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  28. Krok 28: Przycisk SPRAWDŹ

    Kryteria: ,

    R.3.4 Przycisk ma funkcję wysyłania danych (input lub button z typem submit lub button bez typu)

    R.2.8 W bloku prawym podstrony umieszczono formularz z polem edycyjnym i przyciskiem, zastosowano znacznik <form>

    ok. 1 min
    Polecenie z arkusza

    Przycisk „SPRAWDŹ” wysyłający dane

    <button type="submit"> wysyła formularz; stoi w tej samej linii co pole, jak na obrazie 3. Formularz jest kompletny (R.2.8).

    znajdz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a>
                    <ul>
                        <li>w Warszawie</li>
                        <li>w Malborku</li>
                        <li>w Poznaniu</li>
                    </ul>
                </li>
            </ol>
        </section>
        <section id="right">
            <h2>Znajdź kwiaciarnię</h2>
            <form method="post" action="znajdz.php">
                <label>Podaj nazwę miasta: <input type="text" name="city"></label>
                <button type="submit">SPRAWDŹ</button>
            </form>
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  29. Etap 3: Styl CSS

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

    Krok 29: Krój czcionki dla wszystkich elementów

    Kryteria:

    R.4.1 Ustawiono domyślne formatowanie wszystkich selektorów (*): krój czcionki Georgia

    ok. 1 min
    Polecenie z arkusza

    Ustawione domyślne wartości dla wszystkich selektorów stylu CSS: krój czcionki Georgia

    Selektor uniwersalny *.

    styl3.css CSS nowy plik
    * {
        font-family: Georgia;
    }
    Podgląd strony po tym kroku (index.html)
  30. Krok 30: Baner i stopka

    Kryteria:

    R.4.3 Ustawiono biały kolor czcionki dla banera i stopki

    ok. 1 min
    Polecenie z arkusza

    Wspólne dla banera i stopki: kolor tła #C75B39, biały kolor czcionki, marginesy wewnętrzne 10 px, wyrównanie tekstu do środka

    Jedna reguła dla dwóch selektorów; marginesy wewnętrzne to padding.

    styl3.css CSS zmienione: 6 linii
    * {
        font-family: Georgia;
    }
    header, footer {
        background-color: #C75B39;
        color: white;
        padding: 10px;
        text-align: center;
    }
    Podgląd strony po tym kroku (index.html)
  31. Krok 31: Blok lewy

    ok. 1 min
    Polecenie z arkusza

    Dla bloku lewego: kolor tła #FF8A65, szerokość 25%, wysokość 500 px, margines wewnętrzny górny 50 px

    padding-top - tylko górny margines wewnętrzny. Wysokość 500 px dotyczy treści, więc z marginesem blok ma 550 px.

    styl3.css CSS zmienione: 6 linii
    * {
        font-family: Georgia;
    }
    header, footer {
        background-color: #C75B39;
        color: white;
        padding: 10px;
        text-align: center;
    }
    #left {
        background-color: #FF8A65;
        width: 25%;
        height: 500px;
        padding-top: 50px;
    }
    Podgląd strony po tym kroku (index.html)
  32. Krok 32: Blok prawy

    Kryteria: , , ,

    R.4.2 Ustawiono kolor tła #C75B39 dla banera i stopki, #FF8A65 dla bloku lewego i Snow dla prawego

    R.4.5 Ustawiono wysokość 500px dla bloków lewego i prawego

    R.4.6 Ustawiono marginesy wewnętrzne (padding) 10px dla banera i stopki, padding-top: 50px dla bloków lewego i prawego

    R.4.8 Ustawiono wyrównanie tekstu do środka dla banera, stopki i bloku prawego

    ok. 1 min
    Polecenie z arkusza

    Dla bloku prawego: kolor tła Snow, szerokość 75%, wysokość 500 px, wyrównanie tekstu do środka, margines wewnętrzny górny 50 px

    25% + 75% = 100%, więc bloki zmieszczą się obok siebie - górny margines wewnętrzny nie zmienia szerokości. Wszystkie kolory tła, wysokości, wyśrodkowania i marginesy wewnętrzne bloków są ustawione.

    styl3.css CSS zmienione: 7 linii
    * {
        font-family: Georgia;
    }
    header, footer {
        background-color: #C75B39;
        color: white;
        padding: 10px;
        text-align: center;
    }
    #left {
        background-color: #FF8A65;
        width: 25%;
        height: 500px;
        padding-top: 50px;
    }
    #right {
        background-color: Snow;
        width: 75%;
        height: 500px;
        text-align: center;
        padding-top: 50px;
    }
    Podgląd strony po tym kroku (index.html)
  33. Krok 33: Układ bloków zgodny z obrazem 2

    Kryteria:

    R.3.1 Układ bloków po uruchomieniu 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)

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: na górze blok banera, poniżej obok siebie bloki lewy i prawy, na dole blok 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

    Obie <section> dostają float: left i stają obok siebie, a stopka z clear: both zaczyna się dopiero pod nimi.

    styl3.css CSS zmienione: 6 linii
    * {
        font-family: Georgia;
    }
    header, footer {
        background-color: #C75B39;
        color: white;
        padding: 10px;
        text-align: center;
    }
    #left {
        background-color: #FF8A65;
        width: 25%;
        height: 500px;
        padding-top: 50px;
    }
    #right {
        background-color: Snow;
        width: 75%;
        height: 500px;
        text-align: center;
        padding-top: 50px;
    }
    section {
        float: left;
    }
    footer {
        clear: both;
    }
    Podgląd strony po tym kroku (index.html)
  34. Krok 34: Obraz: szerokość, marginesy i cień

    Kryteria: ,

    R.4.4 Ustawiono szerokość 25% dla bloku lewego i 75% dla prawego (width lub grid-template- columns lub flex) oraz 25% dla selektora img

    R.4.9 Ustawiono dla obrazu cień box-shadow: 15px 15px 10px DimGray (poprawnie również 15px 15px 10px 0 DimGray)

    ok. 1 min
    Polecenie z arkusza

    Dla selektora obrazu: szerokość 25%, marginesy zewnętrzne 10 px, cień o przesunięciu 15 px w obu osiach, rozmyciu 10 px i kolorze DimGray

    Selektor znacznika img. Szerokość 25% liczy się od bloku prawego, więc trzy zdjęcia zajmują razem 75% i mieszczą się obok siebie. box-shadow: przesunięcie poziome, pionowe, rozmycie i kolor.

    styl3.css CSS zmienione: 5 linii
    * {
        font-family: Georgia;
    }
    header, footer {
        background-color: #C75B39;
        color: white;
        padding: 10px;
        text-align: center;
    }
    #left {
        background-color: #FF8A65;
        width: 25%;
        height: 500px;
        padding-top: 50px;
    }
    #right {
        background-color: Snow;
        width: 75%;
        height: 500px;
        text-align: center;
        padding-top: 50px;
    }
    section {
        float: left;
    }
    footer {
        clear: both;
    }
    img {
        width: 25%;
        margin: 10px;
        box-shadow: 15px 15px 10px DimGray;
    }
    Podgląd strony po tym kroku (index.html)
  35. Krok 35: Elementy listy: marginesy

    ok. 1 min
    Polecenie z arkusza

    Dla selektora elementu listy: marginesy zewnętrzne 5 px

    Selektor znacznika li - dotyczy elementów obu list, numerowanej i zagnieżdżonej.

    styl3.css CSS zmienione: 3 linie
    * {
        font-family: Georgia;
    }
    header, footer {
        background-color: #C75B39;
        color: white;
        padding: 10px;
        text-align: center;
    }
    #left {
        background-color: #FF8A65;
        width: 25%;
        height: 500px;
        padding-top: 50px;
    }
    #right {
        background-color: Snow;
        width: 75%;
        height: 500px;
        text-align: center;
        padding-top: 50px;
    }
    section {
        float: left;
    }
    footer {
        clear: both;
    }
    img {
        width: 25%;
        margin: 10px;
        box-shadow: 15px 15px 10px DimGray;
    }
    li {
        margin: 5px;
    }
    Podgląd strony po tym kroku (index.html)
  36. Krok 36: Znak markera listy

    Kryteria:

    R.4.10 Ustawiono jedynie dla elementu listy styl pseudoelementu ::marker - kolor czcionki Snow

    ok. 1 min
    Polecenie z arkusza

    Dla znaku markera (punktora / cyfry) w elemencie listy: kolor czcionki Snow

    Pseudoelement ::marker to sam numer albo punktor przed elementem listy - zmienia się tylko jego kolor, tekst zostaje czarny. Na obrazie 2 numery i punktory są prawie niewidoczne, bo Snow to prawie biel.

    Typowe błędy

    li { color: Snow; } zmienia kolor całego tekstu elementu, nie tylko markera - klucz wymaga pseudoelementu ::marker.

    styl3.css CSS zmienione: 3 linie
    * {
        font-family: Georgia;
    }
    header, footer {
        background-color: #C75B39;
        color: white;
        padding: 10px;
        text-align: center;
    }
    #left {
        background-color: #FF8A65;
        width: 25%;
        height: 500px;
        padding-top: 50px;
    }
    #right {
        background-color: Snow;
        width: 75%;
        height: 500px;
        text-align: center;
        padding-top: 50px;
    }
    section {
        float: left;
    }
    footer {
        clear: both;
    }
    img {
        width: 25%;
        margin: 10px;
        box-shadow: 15px 15px 10px DimGray;
    }
    li {
        margin: 5px;
    }
    li::marker {
        color: Snow;
    }
    Podgląd strony po tym kroku (index.html)
  37. Krok 37: Nagłówek trzeciego stopnia: marginesy

    Kryteria:

    R.4.7 Ustawiono marginesy zewnętrzne (margin) 10px dla obrazu, 5px dla selektora li, dla selektora h3 górny i dolny 50px oraz lewy i prawy 0

    ok. 1 min
    Polecenie z arkusza

    Dla selektora nagłówka trzeciego stopnia: marginesy zewnętrzne górny i dolny 50 px, pozostałe 0

    Na stronach w HTML-u nie ma <h3> - wypisze go skrypt z wynikiem wyszukiwania. margin: 50px 0 - pierwsza wartość to górny i dolny, druga lewy i prawy. Wszystkie marginesy zewnętrzne z arkusza są ustawione (R.4.7).

    styl3.css CSS zmienione: 3 linie
    * {
        font-family: Georgia;
    }
    header, footer {
        background-color: #C75B39;
        color: white;
        padding: 10px;
        text-align: center;
    }
    #left {
        background-color: #FF8A65;
        width: 25%;
        height: 500px;
        padding-top: 50px;
    }
    #right {
        background-color: Snow;
        width: 75%;
        height: 500px;
        text-align: center;
        padding-top: 50px;
    }
    section {
        float: left;
    }
    footer {
        clear: both;
    }
    img {
        width: 25%;
        margin: 10px;
        box-shadow: 15px 15px 10px DimGray;
    }
    li {
        margin: 5px;
    }
    li::marker {
        color: Snow;
    }
    h3 {
        margin: 50px 0;
    }
    Podgląd strony po tym kroku (index.html)
  38. Etap 4: Skrypt PHP

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

    Krok 38: 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 kwiaciarnia

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

    ok. 2 min
    Polecenie z arkusza

    Skrypt łączy się z serwerem bazy danych na localhost, użytkownik root bez hasła, baza danych o nazwie kwiaciarnia

    Skrypt stoi w bloku prawym pod formularzem - tam, gdzie ma się pokazać wynik. mysqli_connect z czterema argumentami łączy się z serwerem i od razu wybiera bazę; uchwyt trafia do zmiennej $connection. Druga linia już teraz zamyka połączenie - kolejne instrukcje będą dopisywane nad nią, więc zamknięcie zostanie ostatnią operacją na bazie (R.5.2). Od tego kroku podgląd to wynik prawdziwego uruchomienia znajdz.php po wysłaniu formularza z miastem Warszawa.

    znajdz.php PHP zmienione: 4 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a>
                    <ul>
                        <li>w Warszawie</li>
                        <li>w Malborku</li>
                        <li>w Poznaniu</li>
                    </ul>
                </li>
            </ol>
        </section>
        <section id="right">
            <h2>Znajdź kwiaciarnię</h2>
            <form method="post" action="znajdz.php">
                <label>Podaj nazwę miasta: <input type="text" name="city"></label>
                <button type="submit">SPRAWDŹ</button>
            </form>
            <?php
                $connection = mysqli_connect("localhost", "root", "", "kwiaciarnia");
                mysqli_close($connection);
            ?>
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  39. Krok 39: Dane z pola edycyjnego

    Kryteria:

    R.5.4 Skrypt pobiera dane z tablicy $_POST

    ok. 2 min
    Polecenie z arkusza

    Skrypt pobiera dane z pola edycyjnego

    Wysłany formularz PHP wkłada do tablicy $_POST - pod kluczem "city" (atrybut name pola) jest wpisane miasto. Przy pierwszym otwarciu strony nic nie zostało wysłane, dlatego odczyt stoi w warunku isset; bez niego PHP wypisałby ostrzeżenie „Undefined array key”.

    znajdz.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a>
                    <ul>
                        <li>w Warszawie</li>
                        <li>w Malborku</li>
                        <li>w Poznaniu</li>
                    </ul>
                </li>
            </ol>
        </section>
        <section id="right">
            <h2>Znajdź kwiaciarnię</h2>
            <form method="post" action="znajdz.php">
                <label>Podaj nazwę miasta: <input type="text" name="city"></label>
                <button type="submit">SPRAWDŹ</button>
            </form>
            <?php
                $connection = mysqli_connect("localhost", "root", "", "kwiaciarnia");
                if (isset($_POST["city"])) {
                    $city = $_POST["city"];
                }
                mysqli_close($connection);
            ?>
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

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

  40. Krok 40: Zapytanie 1 z miastem z formularza

    Kryteria:

    R.5.3 Skrypt wysyła do bazy danych zmodyfikowane zapytanie 1 w ten sposób, że w miejscu miasta jest wpisana wartość z pola edycyjnego

    ok. 2 min
    Polecenie z arkusza

    Wysyła do bazy danych zmodyfikowane zapytanie 1 w ten sposób, że w miejscu miasta jest wpisana wartość z pola edycyjnego

    Zapytanie 1, w którym zamiast „Malbork” stoi zmienna $city. Apostrofy wokół niej zostają - w SQL-u tekst musi być w apostrofach. Porównywanie kolumny miasto (utf8mb4_general_ci, zapisane w definicji tabeli w pliku SQL) nie rozróżnia wielkości liter, więc „warszawa” też znajdzie Astrę (sprawdzone).

    znajdz.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a>
                    <ul>
                        <li>w Warszawie</li>
                        <li>w Malborku</li>
                        <li>w Poznaniu</li>
                    </ul>
                </li>
            </ol>
        </section>
        <section id="right">
            <h2>Znajdź kwiaciarnię</h2>
            <form method="post" action="znajdz.php">
                <label>Podaj nazwę miasta: <input type="text" name="city"></label>
                <button type="submit">SPRAWDŹ</button>
            </form>
            <?php
                $connection = mysqli_connect("localhost", "root", "", "kwiaciarnia");
                if (isset($_POST["city"])) {
                    $city = $_POST["city"];
                    $query = "SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = '$city';";
                    $result = mysqli_query($connection, $query);
                }
                mysqli_close($connection);
            ?>
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

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

  41. Krok 41: Nazwa i ulica w nagłówku trzeciego stopnia

    Kryteria:

    R.5.5 Skrypt wyświetla pod przyciskiem zwrócone zapytaniem dane w nagłówku h3: nazwę i ulicę

    ok. 2 min
    Polecenie z arkusza

    Wyświetla pod przyciskiem zwrócone zapytaniem dane w nagłówku trzeciego stopnia: nazwę i ulicę oddzielone przecinkiem

    $row[0] - nazwa, $row[1] - ulica, w kolejności pól zapytania. W mieście może być więcej kwiaciarni, dlatego wiersze odczytuje pętla while - każda kwiaciarnia w osobnym <h3>. Podgląd: „Astra, Sobieskiego” pod przyciskiem, jak na obrazie 3; odstęp nad i pod napisem to marginesy h3 z arkusza stylów.

    znajdz.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a>
                    <ul>
                        <li>w Warszawie</li>
                        <li>w Malborku</li>
                        <li>w Poznaniu</li>
                    </ul>
                </li>
            </ol>
        </section>
        <section id="right">
            <h2>Znajdź kwiaciarnię</h2>
            <form method="post" action="znajdz.php">
                <label>Podaj nazwę miasta: <input type="text" name="city"></label>
                <button type="submit">SPRAWDŹ</button>
            </form>
            <?php
                $connection = mysqli_connect("localhost", "root", "", "kwiaciarnia");
                if (isset($_POST["city"])) {
                    $city = $_POST["city"];
                    $query = "SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = '$city';";
                    $result = mysqli_query($connection, $query);
                    while ($row = mysqli_fetch_row($result)) {
                        echo "<h3>$row[0], $row[1]</h3>";
                    }
                }
                mysqli_close($connection);
            ?>
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  42. Etap 5: Dobre praktyki (poza kluczem)

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

    Krok 42: Zapytanie przygotowane zamiast miasta wklejonego do SQL

    ok. 4 min
    Polecenie z arkusza

    Wysyła do bazy danych zmodyfikowane zapytanie 1 w ten sposób, że w miejscu miasta jest wpisana wartość z pola edycyjnego

    Wersja egzaminacyjna sprawdzona na dwóch wpisach. x' OR '1'='1 wpisane w pole zamienia warunek w miasto = 'x' OR '1'='1', który jest zawsze prawdziwy - strona pokazuje obie kwiaciarnie, choć nie ma miasta „x”. To jest wstrzyknięcie SQL: użytkownik dopisał własny fragment zapytania. Z kolei miasto z apostrofem (literówka albo celowo) psuje składnię, PHP zgłasza wyjątek mysqli_sql_exception i strona urywa się przed stopką.

    Zapytanie przygotowane: mysqli_prepare wysyła zapytanie ze znakiem ? w miejscu miasta, mysqli_stmt_bind_param z typem "s" (tekst) dokłada wartość osobno, a mysqli_stmt_get_result oddaje zwykły wynik - pętla while zostaje bez zmian. Stare linie zostają w komentarzu. Podgląd: ten sam wpis x' OR '1'='1 nie znajduje już żadnej kwiaciarni. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.

    znajdz.php PHP zmienione: 6 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a>
                    <ul>
                        <li>w Warszawie</li>
                        <li>w Malborku</li>
                        <li>w Poznaniu</li>
                    </ul>
                </li>
            </ol>
        </section>
        <section id="right">
            <h2>Znajdź kwiaciarnię</h2>
            <form method="post" action="znajdz.php">
                <label>Podaj nazwę miasta: <input type="text" name="city"></label>
                <button type="submit">SPRAWDŹ</button>
            </form>
            <?php
                $connection = mysqli_connect("localhost", "root", "", "kwiaciarnia");
                if (isset($_POST["city"])) {
                    $city = $_POST["city"];
                    $statement = mysqli_prepare($connection, "SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = ?");
                    mysqli_stmt_bind_param($statement, "s", $city);
                    mysqli_stmt_execute($statement);
                    $result = mysqli_stmt_get_result($statement);
                    // $query = "SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = '$city';";
                    // $result = mysqli_query($connection, $query);
                    while ($row = mysqli_fetch_row($result)) {
                        echo "<h3>$row[0], $row[1]</h3>";
                    }
                }
                mysqli_close($connection);
            ?>
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  43. Krok 43: Komunikat, gdy w mieście nie ma kwiaciarni

    ok. 3 min
    Polecenie z arkusza

    Wyświetla pod przyciskiem zwrócone zapytaniem dane w nagłówku trzeciego stopnia: nazwę i ulicę oddzielone przecinkiem

    W menu jest „w Poznaniu”, a w bazie nie ma kwiaciarni z Poznania - wersja egzaminacyjna po wpisaniu „Poznań” nie pokazuje pod przyciskiem nic i nie wiadomo, czy wyszukiwanie zadziałało. mysqli_num_rows (funkcja z tabeli 1 arkusza) zwraca liczbę znalezionych wierszy; przy zerze skrypt wypisuje „Brak kwiaciarni w mieście Poznań”. Wpisane miasto wraca na stronę, więc przechodzi przez htmlspecialchars - znacznik wpisany w pole nie wykona się jako kod. Podgląd: wyszukiwanie dla Poznania. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.

    znajdz.php PHP zmienione: 5 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl3.css">
    </head>
    <body>
        <header>
            <h1>Grupa Polskich Kwiaciarni</h1>
        </header>
        <section id="left">
            <h2>Menu</h2>
            <ol>
                <li><a href="index.html">Strona główna</a></li>
                <li><a href="https://www.kwiaty.pl/" target="_blank">Rozpoznaj kwiaty</a></li>
                <li><a href="znajdz.php">Znajdź kwiaciarnię</a>
                    <ul>
                        <li>w Warszawie</li>
                        <li>w Malborku</li>
                        <li>w Poznaniu</li>
                    </ul>
                </li>
            </ol>
        </section>
        <section id="right">
            <h2>Znajdź kwiaciarnię</h2>
            <form method="post" action="znajdz.php">
                <label>Podaj nazwę miasta: <input type="text" name="city"></label>
                <button type="submit">SPRAWDŹ</button>
            </form>
            <?php
                $connection = mysqli_connect("localhost", "root", "", "kwiaciarnia");
                if (isset($_POST["city"])) {
                    $city = $_POST["city"];
                    $statement = mysqli_prepare($connection, "SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = ?");
                    mysqli_stmt_bind_param($statement, "s", $city);
                    mysqli_stmt_execute($statement);
                    $result = mysqli_stmt_get_result($statement);
                    // $query = "SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = '$city';";
                    // $result = mysqli_query($connection, $query);
                    if (mysqli_num_rows($result) == 0) {
                        echo "<p>Brak kwiaciarni w mieście " . htmlspecialchars($city) . "</p>";
                    }
                    while ($row = mysqli_fetch_row($result)) {
                        echo "<h3>" . htmlspecialchars("$row[0], $row[1]") . "</h3>";
                        // echo "<h3>$row[0], $row[1]</h3>";
                    }
                }
                mysqli_close($connection);
            ?>
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  44. Etap 6: Oddanie pracy

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

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

    ok. 5 min
    Polecenie z arkusza

    Po zakończeniu pracy utwórz w folderze z numerem zdającego, plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowana była poprawność działania witryny. Nagraj płytę z rezultatami pracy.

    W przeglądarka.txt wystarczy nazwa przeglądarki, w której była sprawdzana strona.

    W folderze: gerbera.jpg, gozdzik.jpg, roza.jpg, index.html, znajdz.php, styl3.css, import.png, kw1.jpg - kw4.jpg, kwerendy.txt i przeglądarka.txt. Po nagraniu płyty trzeba sprawdzić jej odczyt i opisać ją numerem zdającego.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

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

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.