Przejdź do głównej treści
INF.03-03-25.06-SGCzerwiec 2025 · 42 kroki · ok. 94 min · 36 kryteriów z klucza

Rozwiązanie krok po kroku: Portal biblioteki szkolnej (Wersja podstawowa)

Rozwiązanie buduje portal biblioteki szkolnej: baza biblioteka z czterema kwerendami (w tym DELETE i losowanie ORDER BY RAND()), trzy okładki JPEG z pasem książek i tekstem, strona biblioteka.php z tabelą wypełnianą przez PHP i trzema artykułami, style w styles.css z zapytaniami @media oraz skrypt PHP, który wpisuje pięć losowych książek do tabeli.

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ą. Kod PHP jest najpierw pisany funkcjami z tabeli 1 arkusza (proceduralne mysqli), a na końcu zostaje przerobiony na wersję z prawdziwych projektów: nazwy kolumn zamiast numerów, escapowanie danych przed wypisaniem i oddzielenie pracy z bazą od HTML. W tym arkuszu nie ma JavaScriptu.

Obok jest druga wersja tego rozwiązania - zakładka Nowoczesny kod (grid, PDO): te same punkty, ale artykuły na siatce CSS, kolory w zmiennych, PHP na PDO z obsługą błędu i wypisywaniem przez htmlspecialchars od pierwszej linijki.

Grafiki, baza i plik teksty.txt pochodzą z prawdziwego archiwum pliki12 (załącznik do pobrania na stronie arkusza, hasło w treści zadania). Okładki są złożone z plików archiwum tak, jak każe arkusz; zrzuty wyników zapytań są odtworzone z tej bazy - na egzaminie robisz je sam, z całego ekranu.

Jak liczą się punkty. Klucz ma 36 kryteriów (R.1.1 - R.5.6), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 27 punktów - można stracić 9 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 36 kryteriów (pkt)

    Krok 1: Baza danych biblioteka

    Kryteria:

    R.1.1 Wykonany import tabeli do bazy danych biblioteka , czynność udokumentowana w pliku import.png

    ok. 2 min
    Polecenie z arkusza

    Utwórz bazę danych o nazwie biblioteka, z zestawem polskich znaków (np. utf8_unicode_ci).

    W przeglądarce otwierasz http://localhost/phpmyadmin, klikasz Nowa w lewym panelu, wpisujesz nazwę biblioteka i z listy metod porównywania wybierasz utf8_unicode_ci (arkusz podaje ją jako przykład; utf8_polish_ci też jest poprawne). Tabele z pliku SQL mają jednak zestaw utf8mb4 zapisany we własnej definicji, więc nazwiska i tytuły („Woźniak”, „Ślimak i róża”) zachowają ogonki przy każdym wyborze - ustawienie bazy dziedziczą tylko tabele zakładane później bez własnego ustawienia.

    Typowe błędy

    Nazwa bazy musi być dokładnie biblioteka - skrypt PHP łączy się z bazą po nazwie, więc literówka odetnie punkty także za skrypt (R.5.2).

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

    Kryteria:

    R.1.1 Wykonany import tabeli do bazy danych biblioteka , czynność udokumentowana w pliku import.png

    ok. 3 min
    Polecenie z arkusza

    Z rozpakowanego archiwum zaimportuj tabelę z pliku baza.sql do utworzonej bazy.

    Wejdź do bazy biblioteka (musi być zaznaczona w lewym panelu), karta Import, Wybierz plik → baza.sql z rozpakowanego archiwum, Wykonaj. Plik ma prawie 400 kB - import chwilę trwa.

    Po imporcie są dwie tabele z ilustracji 1: ksiazki (id, autor, tytul, kod, data_dodania - 5381 wierszy, cały katalog) i uczniowie (id, nazwisko, imie, klasa, data_wypozyczenia, id_ksiazki - 15 wierszy). Kolumna id_ksiazki to klucz obcy do ksiazki.id - uczeń, który nic nie wypożyczył, ma tam NULL i datę 0000-00-00.

    Typowe błędy

    Import bez wcześniejszego wejścia do bazy biblioteka tworzy tabele w innej bazie (np. test) - skrypt nie znajdzie wtedy tabeli ksiazki.

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

    R.1.1 Wykonany import tabeli do bazy danych biblioteka , czynność udokumentowana w pliku import.png

    ok. 2 min
    Polecenie z arkusza

    Wykonaj zrzut ekranu po imporcie. Zapisz zrzut w formacie PNG pod nazwą import. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań.

    Klawisz Print Screen (cały ekran, nie Alt+PrtScr, który łapie tylko aktywne okno), wklejasz do edytora grafiki i zapisujesz jako import.png w folderze z numerem zdającego. Na zrzucie ma być widać komunikat phpMyAdmin o pomyślnym imporcie albo obie tabele w bazie. W tym arkuszu wszystkie zrzuty (import i kwerendy) są w PNG.

    Typowe błędy

    Wykadrowany zrzut (samo okno przeglądarki, bez paska zadań) nie jest oceniany - klucz mówi to wprost.

  4. Krok 4: Zapytanie 1: wypożyczenia po 2 marca 2020

    Kryteria: ,

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

    R.1.3 Wykonane zapytanie 1 wybierające jedynie nazwisko, imię, klasę i datę wypożyczenia uczniów, dla których data wypożyczenia jest późniejsza niż 2020-03-02. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwisko, imie, klasa, data_wypozyczenia FROM uczniowie WHERE data_wypozyczenia > '2020-03-02'; (data zapisana 02-03-2020 jest błędem) oraz wynik działania zapytania udokumentowany zrzutem, na którym widocznych jest dokładnie 5 rekordów zawierających jedynie pola nazwisko, imie, klasa, data_wypozyczenia (nazwiska: pierwsze Woźniak, ostatnie Kawtan)

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 1: wybierające jedynie nazwisko, imię, klasę i datę wypożyczenia dla uczniów, dla których data wypożyczenia jest późniejsza niż 2020-03-02.

    Zakładka SQL w phpMyAdmin (przy zaznaczonej bazie biblioteka). Klauzula po klauzuli:

    • SELECT nazwisko, imie, klasa, data_wypozyczenia - dokładnie cztery kolumny z arkusza; SELECT * dołożyłby id i id_ksiazki.
    • FROM uczniowie - wszystkie te dane są w jednej tabeli, złączenie nie jest potrzebne.
    • WHERE data_wypozyczenia > '2020-03-02' - „późniejsza niż” to > (bez =, 2 marca odpada). Datę zapisujesz w apostrofach w formacie RRRR-MM-DD, czyli tak, jak trzyma ją baza - klucz wprost mówi, że 02-03-2020 jest błędem.

    Wynik: dokładnie 5 wierszy, od Woźniak (4 marca) do Kawtan (18 marca). Zapytanie kopiujesz do pliku kwerendy.txt i robisz zrzut całego ekranu: kw1.png.

    Typowe błędy

    >= '2020-03-02' dołoży Krakowiaka i Ordak z 2 marca - 7 wierszy zamiast 5. „Późniejsza niż” wyklucza tę datę.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT nazwisko, imie, klasa, data_wypozyczenia FROM uczniowie WHERE data_wypozyczenia > '2020-03-02';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: kto co wypożyczył

    Kryteria:

    R.1.4 Wykonane zapytanie 2 wybierające jedynie nazwisko, imię, datę wypożyczenia oraz odpowiadające im autora i kod książki wypożyczonej przez ucznia. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwisko, imie, data_wypozyczenia, autor, kod FROM uczniowie INNER JOIN ksiazki ON uczniowie.id_ksiazki = ksiazki.id; (możliwe samo JOIN, również z przyrównaniem kluczy po WHERE) oraz wynik działania zapytania udokumentowany zrzutem, na którym widocznych jest dokładnie 7 rekordów dla kodów 2711, 271C, 2719, 277D, 2735, 2739, 2727

    ok. 4 min
    Polecenie z arkusza

    Zapytanie 2: wybierające jedynie nazwisko, imię i datę wypożyczenia oraz odpowiadające im pola autor i kod książki wypożyczonej przez ucznia. Należy posłużyć się relacją.

    Nazwisko i data są w uczniowie, autor i kod w ksiazki - „posłużyć się relacją” znaczy złączyć tabele po kluczu.

    • SELECT nazwisko, imie, data_wypozyczenia, autor, kod - trzy kolumny z jednej tabeli, dwie z drugiej.
    • FROM uczniowie JOIN ksiazki ON ksiazki.id = uczniowie.id_ksiazki - do każdego ucznia dokładasz wiersz książki, której id równa się jego id_ksiazki. Nazwy kolumn poprzedzasz tabelą, bo id jest w obu tabelach. Uczniowie bez książki (id_ksiazki równe NULL) nie mają pary, więc znikają z wyniku - i o to chodzi.

    Wynik: dokładnie 7 wierszy, kody 2711, 271C, 2719, 277D, 2735, 2739, 2727. Zrzut: kw2.png.

    Typowe błędy

    JOIN bez ON daje iloczyn kartezjański: 15 · 5381 wierszy. Klucz przyjmuje też INNER JOIN (to samo co JOIN) i starszy zapis FROM uczniowie, ksiazki WHERE ksiazki.id = id_ksiazki.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT nazwisko, imie, klasa, data_wypozyczenia FROM uczniowie WHERE data_wypozyczenia > '2020-03-02';
    
    -- Zapytanie 2
    SELECT nazwisko, imie, data_wypozyczenia, autor, kod FROM uczniowie JOIN ksiazki ON ksiazki.id = uczniowie.id_ksiazki;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: usunięcie książek bez autora

    Kryteria:

    R.1.5 Wykonane zapytanie 3 usuwające wszystkie rekordy tabeli ksiazki, w których autorowi została przypisana wartość ‘0’ . W pliku z kwerendami lub na zrzucie istnieje zapis np.: DELETE FROM ksiazki WHERE autor = '0'; oraz wynik działania zapytania udokumentowany zrzutem, na którym widoczny jest komunikat o poprawnym usunięciu 621 rekordów lub widoczna tabela z usuniętymi rekordami

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 3: usuwające wszystkie rekordy tabeli ksiazki, w których autorowi została przypisana wartość '0'.

    DELETE FROM ksiazki WHERE autor = '0' - usuwanie wierszy to DELETE FROM z nazwą tabeli (bez listy kolumn - usuwa się całe wiersze), a WHERE mówi które. Kolumna autor jest tekstowa, więc zero porównujesz jako napis w apostrofach, dokładnie tak jak w arkuszu.

    phpMyAdmin zapyta o potwierdzenie - to normalne przy DELETE. Wynik: komunikat o usunięciu 621 rekordów (w tabeli zostaje 4760). Zrzut kw3.png ma pokazać ten komunikat.

    Typowe błędy

    DELETE FROM ksiazki bez WHERE kasuje cały katalog (5381 wierszy) - i nie ma cofania. Przy DELETE zawsze najpierw uruchom SELECT z tym samym WHERE, żeby zobaczyć, co zniknie.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT nazwisko, imie, klasa, data_wypozyczenia FROM uczniowie WHERE data_wypozyczenia > '2020-03-02';
    
    -- Zapytanie 2
    SELECT nazwisko, imie, data_wypozyczenia, autor, kod FROM uczniowie JOIN ksiazki ON ksiazki.id = uczniowie.id_ksiazki;
    
    -- Zapytanie 3
    DELETE FROM ksiazki WHERE autor = '0';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: pięć losowych książek

    Kryteria:

    R.1.6 Wykonane zapytanie 4 wybierające losowo dokładnie pięć rekordów z całej tabeli ksiazki zawierających jedynie pola autor, tytul i kod. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT autor, tytul, kod FROM ksiazki ORDER BY RAND() LIMIT 5; oraz wynik działania zapytania udokumentowany zrzutem, na którym widocznych jest dokładnie 5 rekordów zawierających jedynie pola autor, tytul i kod

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 4: wybierające losowo dokładnie pięć rekordów z całej tabeli ksiazki zawierających jedynie pola autor, tytul i kod.

    • SELECT autor, tytul, kod FROM ksiazki - trzy kolumny z katalogu.
    • ORDER BY RAND() - funkcja RAND() daje dla każdego wiersza losową liczbę, a sortowanie po niej tasuje wiersze. Każde uruchomienie daje inną kolejność.
    • LIMIT 5 - pięć pierwszych po potasowaniu, czyli pięć losowych.

    Wynik: 5 wierszy, za każdym razem innych. Zrzut: kw4.png. To zapytanie wyśle skrypt PHP - dlatego tabela na stronie zmienia się po każdym odświeżeniu. Plik kwerendy.txt ma komplet czterech zapytań.

    Typowe błędy

    LIMIT 5 bez ORDER BY RAND() zwraca zawsze te same pięć pierwszych książek - to nie jest losowanie. ORDER BY RAND() na dużej tabeli jest wolne, ale przy 4760 wierszach nie ma to znaczenia.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT nazwisko, imie, klasa, data_wypozyczenia FROM uczniowie WHERE data_wypozyczenia > '2020-03-02';
    
    -- Zapytanie 2
    SELECT nazwisko, imie, data_wypozyczenia, autor, kod FROM uczniowie JOIN ksiazki ON ksiazki.id = uczniowie.id_ksiazki;
    
    -- Zapytanie 3
    DELETE FROM ksiazki WHERE autor = '0';
    
    -- Zapytanie 4
    SELECT autor, tytul, kod FROM ksiazki ORDER BY RAND() LIMIT 5;
    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 17 z 36 kryteriów (pkt)

    Krok 8: Okładki: pas książek na górze i dole, zapis w JPEG

    Kryteria:

    R.2.1 Motywy książek z grafiki ksiazki.png umieszczone na dole i górze przynajmniej jednej grafiki JPEG z ksiazka1 , ksiazka2 , ksiazka3 . Motyw w całości mieści się w wymiarach książki

    ok. 8 min
    Polecenie z arkusza

    Grafiki ksiazka1, ksiazka2, ksiazka3 zapisane w formacie JPEG. Grafiki ksiazka1.jpg, ksiazka2.jpg, ksiazka3.jpg przekształcone poprzez wklejenie na pierwszy plan książek z pliku ksiazki.png na dole i górze obrazu, powinny one w całości zmieścić się w wymiarach obrazu, patrz ilustracja 2.

    W archiwum są trzy pliki PNG 350 × 480 px z kolorowym polem i szeroki pas książek ksiazki.png (1799 × 314 px). W edytorze grafiki rastrowej (np. GIMP) dla każdej okładki:

    1. otwierasz ksiazka1.png, a pas książek wczytujesz jako nową warstwę (Plik → Otwórz jako warstwy),
    2. skalujesz warstwę do szerokości ok. 330 px (Warstwa → Skaluj warstwę, z zachowaniem proporcji) - musi się w całości zmieścić w 350 px szerokości obrazu,
    3. przesuwasz ją na górę, duplikujesz warstwę i drugą kopię przesuwasz na dół,
    4. eksportujesz jako ksiazka1.jpg (Plik → Wyeksportuj jako, rozszerzenie .jpg).

    To samo dla ksiazka2 i ksiazka3. Klucz R.2.1 sprawdza przynajmniej jedną okładkę, ale strona potrzebuje trzech.

    Typowe błędy

    Pas książek wklejony w pełnej szerokości 1799 px wystaje poza obraz - klucz wymaga, żeby motyw w całości mieścił się w wymiarach okładki. Zapis .png zamiast .jpg to brak pliku, do którego odwoła się strona.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Okładki: autor i tytuł czcionką szeryfową

    Kryteria:

    R.2.2 Na przynajmniej jednej grafice umieszczony autor i tytuł. Zastosowana czcionka szeryfowa, tytuły zostały pogrubione

    ok. 6 min
    Polecenie z arkusza

    W grafice ksiazka1.jpg w niebieskim polu umieszczony tekst „HANS CHRISTIAN ANDERSEN Ropucha”. W grafice ksiazka2.jpg w zielonym polu umieszczony tekst „MARIA KONOPNICKA Przygoda z lalką”. W grafice ksiazka3.jpg w fioletowym polu umieszczony tekst „IGNACY KRASICKI Przyjaciel”. Tekst zapisany jest czcionką szeryfową, tytuł jest dodatkowo pogrubiony.

    Narzędzie Tekst w GIMP-ie, klik w kolorowe pole. Czcionka szeryfowa to np. Times New Roman albo Georgia (litery mają „stopki”; Arial i Verdana są bezszeryfowe - to byłby błąd). Autor wielkimi literami, jak w arkuszu; tytuł w osobnej linii z wariantem Bold. Tekst musi mieścić się w polu - na ilustracji 2 autor jest w dwóch liniach.

    Po dodaniu tekstu eksportujesz jeszcze raz do .jpg. Klucz R.2.2 sprawdza czcionkę szeryfową i pogrubienie tytułu na przynajmniej jednej okładce.

    Typowe błędy

    Cały tekst pogrubiony albo cały zwykły - arkusz mówi „tytuł dodatkowo pogrubiony”, więc autor zwykły, tytuł bold. Domyślna czcionka GIMP-a (Sans) jest bezszeryfowa.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 9
  10. Krok 10: Plik biblioteka.php w HTML5

    Kryteria:

    R.2.3 W pliku biblioteka.php zapisana deklaracja HTML5 <!DOCTYPE HTML>, deklaracja języka zawartości: polski np. <html lang="pl">, w sekcji head znajduje się jawnie podany standard kodowania polskich znaków

    ok. 2 min
    Polecenie z arkusza

    Składa się ze strony o nazwie biblioteka.php. Zapisana w języku HTML5.

    W edytorze zaznaczającym składnię tworzysz plik biblioteka.php w folderze zdającego, obok okładek. Rozszerzenie .php, bo dojdzie skrypt PHP - na razie to czysty HTML.

    Pierwsza linia <!DOCTYPE html> mówi przeglądarce, że dokument jest w HTML5. Dalej szkielet każdej strony: <html>, a w nim <head> (informacje o stronie) i <body> (to, co widać w oknie).

    biblioteka.php PHP nowy plik
    <!DOCTYPE html>
    <html>
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (biblioteka.php)
  11. Krok 11: Język strony

    Kryteria:

    R.2.3 W pliku biblioteka.php zapisana deklaracja HTML5 <!DOCTYPE HTML>, deklaracja języka zawartości: polski np. <html lang="pl">, w sekcji head znajduje się jawnie podany standard kodowania polskich znaków

    ok. 1 min
    Polecenie z arkusza

    Zadeklarowany polski język zawartości witryny.

    Atrybut lang="pl" w znaczniku <html>. Czytnik ekranu czyta wtedy tekst polską wymową, a przeglądarka dobiera słownik. Na stronie nic się nie zmienia - to informacja dla programów.

    biblioteka.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (biblioteka.php)
  12. Krok 12: Kodowanie polskich znaków

    Kryteria:

    R.2.3 W pliku biblioteka.php zapisana deklaracja HTML5 <!DOCTYPE HTML>, deklaracja języka zawartości: polski np. <html lang="pl">, w sekcji head znajduje się jawnie podany standard kodowania polskich znaków

    ok. 1 min
    Polecenie z arkusza

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

    <meta charset="UTF-8"> jako pierwsza rzecz w <head>. „Jawnie” znaczy: wpisane w kodzie, nie zdane na domysł przeglądarki. Bez tej linii tytuły z bazy („Ślimak i róża”) mogłyby wyświetlić się jako krzaki. Plik trzeba też zapisać w UTF-8.

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

    Kryteria:

    R.2.4 Nadany tytuł stronie "BIBLIOTEKA SZKOLNA”

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony „BIBLIOTEKA SZKOLNA” widoczny na karcie przeglądarki.

    <title> w <head> - napis na karcie przeglądarki, nie nagłówek na stronie. Klucz R.2.4 sprawdza tekst „BIBLIOTEKA SZKOLNA” (wielkość liter klucz toleruje, ale przepisujesz dokładnie).

    biblioteka.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (biblioteka.php)
  14. Krok 14: Podpięcie arkusza stylów

    Kryteria:

    R.3.2 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styles.css formatowanie CSS pochodzi jedynie z tego arkusza

    ok. 1 min
    Polecenie z arkusza

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

    <link rel="stylesheet" href="styles.css"> w <head>. Uwaga na nazwę: w tym arkuszu to styles.css (z „s” na końcu), nie styl.css jak w wielu innych - klucz R.3.2 sprawdza dokładnie tę nazwę. Plik napiszesz po HTML.

    Typowe błędy

    href="styl.css" z przyzwyczajenia po innych arkuszach - przeglądarka nie znajdzie pliku i cały rezultat R.4 przepada, bo „formatowanie CSS pochodzi jedynie z tego arkusza”.

    biblioteka.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (biblioteka.php)
  15. Krok 15: Bloki semantyczne

    Kryteria:

    R.2.5 W sekcji body zdefiniowany jest podział na bloki za pomocą semantycznych znaczników HTML 5: header, section, main -> article + article + article, footer

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki zrealizowany za pomocą semantycznych znaczników bloków języka HTML5 tak, aby po uruchomieniu w przeglądarce układ bloków na stronie był zgodny z ilustracją 3.

    Z ilustracji 3: blok nagłówkowy, pod nim blok sekcji, potem blok główny z trzema blokami artykułu obok siebie, na dole stopka. Klucz R.2.5 wymienia znaczniki wprost: <header>, <section>, <main> z trzema <article> w środku, <footer>.

    Artykuły dostają identyfikatory book1, book2, book3, bo każdy będzie miał inny kolor tła. Nazwy identyfikatorów, klas i zmiennych piszesz w tym rozwiązaniu po angielsku (arkusz dopuszcza polski lub angielski, wymaga konsekwencji); wyjątkiem są nazwy narzucone przez arkusz (biblioteka.php, styles.css, kolumny bazy). To, że artykuły staną obok siebie, zrobi CSS.

    Typowe błędy

    Artykuły poza <main> (np. bezpośrednio w <body>) nie spełniają R.2.5 - klucz mówi „main → article + article + article”, czyli artykuły wewnątrz bloku głównego.

    biblioteka.php PHP zmienione: 14 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
        </header>
        <section>
        </section>
        <main>
            <article id="book1">
            </article>
            <article id="book2">
            </article>
            <article id="book3">
            </article>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biblioteka.php)
  16. Krok 16: Nagłówek strony

    Kryteria:

    R.2.6 Zapisane w bloku nagłówkowym <h2>: "STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN", w bloku sekcji <h3>: "Nasze dzisiejsze propozycje:" oraz paragraf w przynajmniej jednym bloku artykułu

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku nagłówkowego: nagłówek drugiego stopnia o treści: „STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN”.

    Drugiego stopnia to <h2>. Treść kopiujesz z pierwszej linii teksty.txt - arkusz mówi wprost, że teksty można stamtąd skopiować, więc nie przepisujesz ich ręcznie.

    biblioteka.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
        </section>
        <main>
            <article id="book1">
            </article>
            <article id="book2">
            </article>
            <article id="book3">
            </article>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biblioteka.php)
  17. Krok 17: Sekcja: nagłówek „Nasze dzisiejsze propozycje:”

    Kryteria:

    R.2.6 Zapisane w bloku nagłówkowym <h2>: "STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN", w bloku sekcji <h3>: "Nasze dzisiejsze propozycje:" oraz paragraf w przynajmniej jednym bloku artykułu

    ok. 1 min
    Polecenie z arkusza

    Zawartość sekcji: nagłówek trzeciego stopnia o treści: „Nasze dzisiejsze propozycje:”.

    <h3> w <section>, z dwukropkiem, jak w arkuszu i w teksty.txt.

    biblioteka.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
            <h3>Nasze dzisiejsze propozycje:</h3>
        </section>
        <main>
            <article id="book1">
            </article>
            <article id="book2">
            </article>
            <article id="book3">
            </article>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biblioteka.php)
  18. Krok 18: Sekcja: tabela z wierszem nagłówkowym

    Kryteria: ,

    R.2.9 W bloku sekcji umieszczono tabelę o 3 kolumnach (w skrypcie lub HTML) zastosowane znaczniki <table>, <tr>, <td>

    R.2.10 Pierwszy wiersz tabeli zawiera komórki nagłówkowe, zastosowane znaczniki <tr>, <th>

    ok. 2 min
    Polecenie z arkusza

    Tabela o trzech kolumnach, w której pierwszy wiersz zawiera komórki nagłówkowe o treści: Autor, Tytuł, Katalog. Tabela jest wypełniona przez skrypt.

    <table> z jednym wierszem <tr>, w którym są komórki nagłówkowe <th> - nie <td>. To osobne kryterium (R.2.10) i częsta strata punktu. Kolejne wiersze z książkami dopisze skrypt PHP, więc w HTML jest tylko nagłówek.

    biblioteka.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
            <h3>Nasze dzisiejsze propozycje:</h3>
            <table>
                <tr><th>Autor</th><th>Tytuł</th><th>Katalog</th></tr>
            </table>
        </section>
        <main>
            <article id="book1">
            </article>
            <article id="book2">
            </article>
            <article id="book3">
            </article>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biblioteka.php)
  19. Krok 19: Pierwszy artykuł: okładka

    Kryteria:

    R.2.7 W przynajmniej jednym bloku artykułu umieszczony obraz ksiazka1 lub ksiazka2 , lub ksiazka3. Obraz ma tekst alternatywny "okładka książki"

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku głównego: trzy bloki artykułu. W każdym bloku artykułu znajdują się: grafika, kolejno ksiazka1.jpg, ksiazka2.jpg, ksiazka3.jpg z tekstami alternatywnymi o treści „okładka książki”.

    <img src="ksiazka1.jpg" alt="okładka książki"> w pierwszym artykule - to plik JPEG złożony w etapie grafiki, leżący obok biblioteka.php. Tekst alternatywny jest ten sam dla wszystkich trzech okładek, dokładnie z arkusza. W podglądzie obraz ma na razie naturalny rozmiar 350 × 480 px - szerokość ustawi CSS.

    Typowe błędy

    src="ksiazka1.png" wskazuje plik źródłowy z archiwum, nie przerobioną okładkę - strona pokaże pustą okładkę bez książek i tekstu.

    biblioteka.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
            <h3>Nasze dzisiejsze propozycje:</h3>
            <table>
                <tr><th>Autor</th><th>Tytuł</th><th>Katalog</th></tr>
            </table>
        </section>
        <main>
            <article id="book1">
                <img src="ksiazka1.jpg" alt="okładka książki">
            </article>
            <article id="book2">
            </article>
            <article id="book3">
            </article>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biblioteka.php)
  20. Krok 20: Pierwszy artykuł: streszczenie

    Kryteria:

    R.2.6 Zapisane w bloku nagłówkowym <h2>: "STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN", w bloku sekcji <h3>: "Nasze dzisiejsze propozycje:" oraz paragraf w przynajmniej jednym bloku artykułu

    ok. 1 min
    Polecenie z arkusza

    Paragraf zawierający odpowiedni tekst streszczenia - patrz ilustracja 2 oraz plik teksty.txt.

    <p> pod obrazem, z tekstem skopiowanym z teksty.txt - zdanie pod „Hans Christian Andersen - Ropucha”. Kopiuj (Ctrl+C / Ctrl+V), nie przepisuj: wielokropek i przecinki mają się zgadzać. Klucz R.2.6 wymaga paragrafu w przynajmniej jednym artykule.

    biblioteka.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
            <h3>Nasze dzisiejsze propozycje:</h3>
            <table>
                <tr><th>Autor</th><th>Tytuł</th><th>Katalog</th></tr>
            </table>
        </section>
        <main>
            <article id="book1">
                <img src="ksiazka1.jpg" alt="okładka książki">
                <p>Według różnych podań najpaskudniejsza ropucha nosi w głowie piękny, cenny klejnot.</p>
            </article>
            <article id="book2">
            </article>
            <article id="book3">
            </article>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biblioteka.php)
  21. Krok 21: Drugi i trzeci artykuł

    Kryteria: ,

    R.2.6 Zapisane w bloku nagłówkowym <h2>: "STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN", w bloku sekcji <h3>: "Nasze dzisiejsze propozycje:" oraz paragraf w przynajmniej jednym bloku artykułu

    R.2.7 W przynajmniej jednym bloku artykułu umieszczony obraz ksiazka1 lub ksiazka2 , lub ksiazka3. Obraz ma tekst alternatywny "okładka książki"

    ok. 2 min
    Polecenie z arkusza

    Grafika, kolejno ksiazka1.jpg, ksiazka2.jpg, ksiazka3.jpg z tekstami alternatywnymi o treści „okładka książki”. Paragraf zawierający odpowiedni tekst streszczenia.

    Ten sam wzorzec dla book2 (Konopnicka) i book3 (Krasicki): obraz z kolejnym numerem i paragraf ze streszczeniem z teksty.txt. Kolejność artykułów odpowiada kolejności okładek i tekstów w pliku.

    biblioteka.php PHP zmienione: 4 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
            <h3>Nasze dzisiejsze propozycje:</h3>
            <table>
                <tr><th>Autor</th><th>Tytuł</th><th>Katalog</th></tr>
            </table>
        </section>
        <main>
            <article id="book1">
                <img src="ksiazka1.jpg" alt="okładka książki">
                <p>Według różnych podań najpaskudniejsza ropucha nosi w głowie piękny, cenny klejnot.</p>
            </article>
            <article id="book2">
                <img src="ksiazka2.jpg" alt="okładka książki">
                <p>Panna Stefcia i Maryla nie są to zbyt grzeczne damy, nawet nie słuchają mamy...</p>
            </article>
            <article id="book3">
                <img src="ksiazka3.jpg" alt="okładka książki">
                <p>Ratuj mnie, przyjacielu, w ostatniej potrzebie: Kocham piękną Irenę. Rodzice i ona...</p>
            </article>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biblioteka.php)
  22. Krok 22: Stopka z numerem zdającego

    Kryteria:

    R.2.8 W bloku stopki wstawiony został numer zdającego

    ok. 1 min
    Polecenie z arkusza

    Zawartość stopki: napis „Stronę wykonał: ”, dalej wstawiony numer zdającego.

    Napis w <footer> - dajesz go w paragrafie <p>, choć arkusz nie wymaga tu konkretnego znacznika. W tym rozwiązaniu po dwukropku stoi nazwisko autora - na egzaminie wpisujesz swój numer zdającego (PESEL), bo tego sprawdza klucz R.2.8. Struktura HTML strony jest kompletna - dalej style.

    biblioteka.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
            <h3>Nasze dzisiejsze propozycje:</h3>
            <table>
                <tr><th>Autor</th><th>Tytuł</th><th>Katalog</th></tr>
            </table>
        </section>
        <main>
            <article id="book1">
                <img src="ksiazka1.jpg" alt="okładka książki">
                <p>Według różnych podań najpaskudniejsza ropucha nosi w głowie piękny, cenny klejnot.</p>
            </article>
            <article id="book2">
                <img src="ksiazka2.jpg" alt="okładka książki">
                <p>Panna Stefcia i Maryla nie są to zbyt grzeczne damy, nawet nie słuchają mamy...</p>
            </article>
            <article id="book3">
                <img src="ksiazka3.jpg" alt="okładka książki">
                <p>Ratuj mnie, przyjacielu, w ostatniej potrzebie: Kocham piękną Irenę. Rodzice i ona...</p>
            </article>
        </main>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biblioteka.php)
  23. Etap 3: Styl CSS

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

    Krok 23: Plik styles.css: krój czcionki i wyrównanie

    Kryteria:

    R.4.1 Ustawione domyślne formatowanie wszystkich selektorów (*): krój czcionki Roboto, w przypadku jego braku Arial, sans-serif, wyrównanie tekstu do środka

    ok. 2 min
    Polecenie z arkusza

    Domyślnie dla wszystkich selektorów: krój czcionki: Roboto, w przypadku jego braku Arial, sans-serif, wyrównanie tekstu do środka.

    Utwórz plik styles.css obok biblioteka.php. „Wszystkie selektory” to selektor uniwersalny *. font-family przyjmuje listę krojów po przecinku: przeglądarka bierze pierwszy, który ma zainstalowany - Roboto, a gdy go brak, Arial, a w ostateczności dowolną czcionkę bezszeryfową (sans-serif). Arkusz podaje tę kolejność wprost. text-align: center wyśrodkowuje cały tekst strony.

    Typowe błędy

    font-family: Roboto bez zapasowych krojów - na komputerze egzaminatora bez Roboto strona pokaże domyślną czcionkę przeglądarki (szeryfową), a klucz R.4.1 wymienia całą listę.

    styles.css CSS nowy plik
    * {
        font-family: Roboto, Arial, sans-serif;
        text-align: center;
    }
    Podgląd strony po tym kroku (biblioteka.php)
  24. Krok 24: Ciało strony: kolor tła

    Kryteria:

    R.4.2 Ustawiony kolor tła LightCyan dla selektora body

    ok. 1 min
    Polecenie z arkusza

    Dla selektora ciała strony: kolor tła LightCyan.

    Selektor znacznika body - arkusz podkreśla na stronie 5, że tło ciała strony ma być ustawione wyłącznie selektorem znacznika, nie klasą ani id. Tło całego okna robi się jasnobłękitne.

    styles.css CSS zmienione: 3 linie
    * {
        font-family: Roboto, Arial, sans-serif;
        text-align: center;
    }
    body {
        background-color: LightCyan;
    }
    Podgląd strony po tym kroku (biblioteka.php)
  25. Krok 25: Nagłówek i stopka: tło, kolor tekstu, margines wewnętrzny

    Kryteria: , ,

    R.4.3 Ustawiony kolor tła bloku nagłówkowego i stopki SteelBlue, pierwszy blok artykułu DodgerBlue, drugi - LimeGreen, trzeci - DarkOrchid

    R.4.4 Ustawiony dla bloku nagłówkowego i stopki biały kolor czcionki

    R.4.7 Ustawione marginesy wewnętrzne (padding) 10px dla bloków nagłówkowego i stopki, 20px dla selektora paragrafu oraz margines górny (padding-top) 40px dla trzech bloków artykułu

    ok. 1 min
    Polecenie z arkusza

    Dla bloku nagłówkowego i stopki: kolor tła SteelBlue, biały kolor czcionki, marginesy wewnętrzne 10 px.

    Wspólne cechy dwóch bloków piszesz raz - selektory po przecinku header, footer. Margines wewnętrzny to padding (zewnętrzny byłby margin). Nagłówek i stopka stają się stalowoniebieskimi pasami z białym tekstem, jak na ilustracji 2.

    styles.css CSS zmienione: 5 linii
    * {
        font-family: Roboto, Arial, sans-serif;
        text-align: center;
    }
    body {
        background-color: LightCyan;
    }
    header, footer {
        background-color: SteelBlue;
        color: white;
        padding: 10px;
    }
    Podgląd strony po tym kroku (biblioteka.php)
  26. Krok 26: Artykuły: margines górny wewnętrzny i marginesy zewnętrzne

    Kryteria: ,

    R.4.7 Ustawione marginesy wewnętrzne (padding) 10px dla bloków nagłówkowego i stopki, 20px dla selektora paragrafu oraz margines górny (padding-top) 40px dla trzech bloków artykułu

    R.4.8 Ustawione marginesy zewnętrzne (margin) 1% dla trzech bloków artykułu, auto dla tabeli

    ok. 1 min
    Polecenie z arkusza

    Dla wszystkich bloków artykułu: margines wewnętrzny górny 40 px, marginesy zewnętrzne 1%.

    Selektor znacznika article obejmuje wszystkie trzy bloki. padding-top: 40px to margines wewnętrzny tylko z góry (miejsce nad okładką), margin: 1% - odstęp zewnętrzny z każdej strony, liczony od szerokości rodzica. Układ obok siebie zrobisz w następnych dwóch krokach.

    styles.css CSS zmienione: 4 linie
    * {
        font-family: Roboto, Arial, sans-serif;
        text-align: center;
    }
    body {
        background-color: LightCyan;
    }
    header, footer {
        background-color: SteelBlue;
        color: white;
        padding: 10px;
    }
    article {
        padding-top: 40px;
        margin: 1%;
    }
    Podgląd strony po tym kroku (biblioteka.php)
  27. Krok 27: Szerokie ekrany: trzy artykuły obok siebie

    Kryteria: , ,

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z ilustracją 3 w arkuszu egzaminacyjnym dla szerokości powyżej 800 px (prawidłowo zastosowane właściwości CSS decydujące o układzie bloków na stronie, np. float i clear albo display flex albo grid albo position)

    R.3.4 Po zwiększeniu szerokości okna przeglądarki jedynie dla 800 px i powyżej bloki w bloku głównym są ustawione obok siebie

    R.4.5 Zdefiniowane reguły @media dla trzech bloków artykułu: dla reguły szerokości ekranu 800px i więcej - szerokość bloku 30% w przeciwnym przypadku szerokość bloku 98% (width lub grid-template-columns lub flex)

    ok. 3 min
    Polecenie z arkusza

    Gdy szerokość ekranu wynosi 800 px i więcej, trzy bloki są wyświetlane obok siebie, ich szerokość wynosi 30%.

    Zapytanie medialne @media (min-width: 800px) { ... } - reguły w środku działają tylko, gdy okno ma 800 px lub więcej (tabela 2 arkusza opisuje @media). W środku: width: 30% i float: left, żeby artykuły pływały obok siebie. Trzy razy 30% plus marginesy po 1% z każdej strony to 96% - mieszczą się w jednym wierszu. Stopka dostaje clear: both, żeby wróciła pod pływające artykuły.

    Klucz R.3.4 sprawdza granicę dokładnie: przy 800 px bloki mają być obok siebie - stąd min-width: 800px, nie 801px. Klucz przyjmuje też display: flex albo grid.

    Typowe błędy

    @media (min-width: 801px) zostawia dokładnie 800 px w układzie pod sobą - klucz R.3.4 mówi „dla 800 px i powyżej obok siebie”.

    styles.css CSS zmienione: 9 linii
    * {
        font-family: Roboto, Arial, sans-serif;
        text-align: center;
    }
    body {
        background-color: LightCyan;
    }
    header, footer {
        background-color: SteelBlue;
        color: white;
        padding: 10px;
    }
    article {
        padding-top: 40px;
        margin: 1%;
    }
    @media (min-width: 800px) {
        article {
            width: 30%;
            float: left;
        }
        footer {
            clear: both;
        }
    }
    Podgląd strony po tym kroku (biblioteka.php)
  28. Krok 28: Wąskie ekrany: artykuły jeden pod drugim

    Kryteria: ,

    R.3.3 Po zmniejszeniu szerokości okna przeglądarki jedynie poniżej 800 px bloki w bloku głównym są ustawione jeden pod drugim

    R.4.5 Zdefiniowane reguły @media dla trzech bloków artykułu: dla reguły szerokości ekranu 800px i więcej - szerokość bloku 30% w przeciwnym przypadku szerokość bloku 98% (width lub grid-template-columns lub flex)

    ok. 2 min
    Polecenie z arkusza

    Gdy szerokość ekranu jest mniejsza niż 800 px szerokość każdego z trzech bloków wynosi 98% (są wyświetlane jeden pod drugim) zgodnie z ilustracją 4.

    Drugie zapytanie medialne, @media (max-width: 799px) - okno węższe niż 800 px. Artykuły dostają width: 98% (plus 1% marginesu z każdej strony = 100%) i bez float stoją jeden pod drugim, jak na ilustracji 4. Sprawdź w podglądzie, zwężając okno - egzaminator robi to samo (R.3.3).

    Typowe błędy

    Jedna reguła article { width: 30% } bez @media daje wąskie bloki także na telefonie - R.3.3 i R.4.5 wymagają dwóch szerokości zależnych od okna.

    styles.css CSS zmienione: 5 linii
    * {
        font-family: Roboto, Arial, sans-serif;
        text-align: center;
    }
    body {
        background-color: LightCyan;
    }
    header, footer {
        background-color: SteelBlue;
        color: white;
        padding: 10px;
    }
    article {
        padding-top: 40px;
        margin: 1%;
    }
    @media (min-width: 800px) {
        article {
            width: 30%;
            float: left;
        }
        footer {
            clear: both;
        }
    }
    @media (max-width: 799px) {
        article {
            width: 98%;
        }
    }
    Podgląd strony po tym kroku (biblioteka.php)
  29. Krok 29: Artykuły: trzy kolory tła

    Kryteria:

    R.4.3 Ustawiony kolor tła bloku nagłówkowego i stopki SteelBlue, pierwszy blok artykułu DodgerBlue, drugi - LimeGreen, trzeci - DarkOrchid

    ok. 2 min
    Polecenie z arkusza

    Dodatkowo dla pierwszego artykułu: kolor tła DodgerBlue. Dodatkowo dla drugiego artykułu: kolor tła LimeGreen. Dodatkowo dla trzeciego artykułu: kolor tła DarkOrchid.

    Trzy reguły po identyfikatorach #book1, #book2, #book3 - każdy artykuł inny kolor, dokładnie jak na ilustracji 2 (niebieski, zielony, fioletowy - pasujące do pól na okładkach). Identyfikatory są tu dozwolone, bo każdy artykuł jest jeden. Klucz przyjmuje też article:nth-of-type(1) i podobne.

    styles.css CSS zmienione: 9 linii
    * {
        font-family: Roboto, Arial, sans-serif;
        text-align: center;
    }
    body {
        background-color: LightCyan;
    }
    header, footer {
        background-color: SteelBlue;
        color: white;
        padding: 10px;
    }
    article {
        padding-top: 40px;
        margin: 1%;
    }
    @media (min-width: 800px) {
        article {
            width: 30%;
            float: left;
        }
        footer {
            clear: both;
        }
    }
    @media (max-width: 799px) {
        article {
            width: 98%;
        }
    }
    #book1 {
        background-color: DodgerBlue;
    }
    #book2 {
        background-color: LimeGreen;
    }
    #book3 {
        background-color: DarkOrchid;
    }
    Podgląd strony po tym kroku (biblioteka.php)
  30. Krok 30: Obraz: szerokość 70%

    Kryteria:

    R.4.6 Ustawiona szerokość dla selektora img oraz selektora table na 70%

    ok. 1 min
    Polecenie z arkusza

    Dla selektora obrazu: szerokość 70%.

    Selektor znacznika img (arkusz wymaga selektora znacznika, nie klasy). width: 70% liczy się od szerokości artykułu - okładka zmniejsza się razem z oknem, wysokość przelicza się proporcjonalnie. Dzięki text-align: center z * obraz stoi na środku artykułu.

    styles.css CSS zmienione: 3 linie
    * {
        font-family: Roboto, Arial, sans-serif;
        text-align: center;
    }
    body {
        background-color: LightCyan;
    }
    header, footer {
        background-color: SteelBlue;
        color: white;
        padding: 10px;
    }
    article {
        padding-top: 40px;
        margin: 1%;
    }
    @media (min-width: 800px) {
        article {
            width: 30%;
            float: left;
        }
        footer {
            clear: both;
        }
    }
    @media (max-width: 799px) {
        article {
            width: 98%;
        }
    }
    #book1 {
        background-color: DodgerBlue;
    }
    #book2 {
        background-color: LimeGreen;
    }
    #book3 {
        background-color: DarkOrchid;
    }
    img {
        width: 70%;
    }
    Podgląd strony po tym kroku (biblioteka.php)
  31. Krok 31: Paragraf: margines wewnętrzny

    Kryteria:

    R.4.7 Ustawione marginesy wewnętrzne (padding) 10px dla bloków nagłówkowego i stopki, 20px dla selektora paragrafu oraz margines górny (padding-top) 40px dla trzech bloków artykułu

    ok. 1 min
    Polecenie z arkusza

    Dla selektora paragrafu: marginesy wewnętrzne 20 px.

    Selektor znacznika p, padding: 20px - streszczenia odsuwają się od krawędzi kolorowych artykułów. Reguła obejmie też paragraf w stopce - to zgodne z arkuszem („dla selektora paragrafu”).

    styles.css CSS zmienione: 3 linie
    * {
        font-family: Roboto, Arial, sans-serif;
        text-align: center;
    }
    body {
        background-color: LightCyan;
    }
    header, footer {
        background-color: SteelBlue;
        color: white;
        padding: 10px;
    }
    article {
        padding-top: 40px;
        margin: 1%;
    }
    @media (min-width: 800px) {
        article {
            width: 30%;
            float: left;
        }
        footer {
            clear: both;
        }
    }
    @media (max-width: 799px) {
        article {
            width: 98%;
        }
    }
    #book1 {
        background-color: DodgerBlue;
    }
    #book2 {
        background-color: LimeGreen;
    }
    #book3 {
        background-color: DarkOrchid;
    }
    img {
        width: 70%;
    }
    p {
        padding: 20px;
    }
    Podgląd strony po tym kroku (biblioteka.php)
  32. Krok 32: Tabela: wyśrodkowanie, szerokość, obramowanie

    Kryteria: , ,

    R.4.6 Ustawiona szerokość dla selektora img oraz selektora table na 70%

    R.4.8 Ustawione marginesy zewnętrzne (margin) 1% dla trzech bloków artykułu, auto dla tabeli

    R.4.9 Ustawione obramowanie tabeli linią ciągłą o kolorze SteelBlue i szerokości 1px

    ok. 2 min
    Polecenie z arkusza

    Dla selektora tabeli: wyśrodkowanie tabeli, szerokość 70%, obramowanie linią ciągłą o kolorze SteelBlue i szerokości 1 px.

    Selektor znacznika table. „Wyśrodkowanie tabeli” to margin: auto przy ustalonej szerokości (klucz R.4.8 mówi wprost: „auto dla tabeli”) - text-align: center wyśrodkowałby tylko tekst w komórkach, nie samą tabelę. Skrót border: 1px solid SteelBlue łączy grubość, styl (ciągła) i kolor.

    Typowe błędy

    Styl tabeli przez klasę (.tabela) nie spełnia wymagania - arkusz zastrzega selektor znacznika „ze względu na projekt późniejszej rozbudowy witryny”.

    styles.css CSS zmienione: 5 linii
    * {
        font-family: Roboto, Arial, sans-serif;
        text-align: center;
    }
    body {
        background-color: LightCyan;
    }
    header, footer {
        background-color: SteelBlue;
        color: white;
        padding: 10px;
    }
    article {
        padding-top: 40px;
        margin: 1%;
    }
    @media (min-width: 800px) {
        article {
            width: 30%;
            float: left;
        }
        footer {
            clear: both;
        }
    }
    @media (max-width: 799px) {
        article {
            width: 98%;
        }
    }
    #book1 {
        background-color: DodgerBlue;
    }
    #book2 {
        background-color: LimeGreen;
    }
    #book3 {
        background-color: DarkOrchid;
    }
    img {
        width: 70%;
    }
    p {
        padding: 20px;
    }
    table {
        margin: auto;
        width: 70%;
        border: 1px solid SteelBlue;
    }
    Podgląd strony po tym kroku (biblioteka.php)
  33. Krok 33: Wiersz tabeli pod kursorem

    Kryteria:

    R.4.10 W momencie gdy kursor myszy znajdzie się na wierszu tabeli, jego kolor tła zmienia się na SteelBlue, a kolor czcionki na biały, np. tr:hover

    ok. 1 min
    Polecenie z arkusza

    W momencie gdy kursor myszy znajdzie się na wierszu tabeli, jego kolor tła zmienia się na SteelBlue, a kolor czcionki na biały.

    Pseudoklasa :hover na wierszu tr - klucz R.4.10 podaje ten zapis jako przykład. Efekt zobaczysz, gdy skrypt wypełni tabelę (na razie jest tylko wiersz nagłówkowy, on też reaguje). Arkusz stylów jest kompletny.

    styles.css CSS zmienione: 4 linie
    * {
        font-family: Roboto, Arial, sans-serif;
        text-align: center;
    }
    body {
        background-color: LightCyan;
    }
    header, footer {
        background-color: SteelBlue;
        color: white;
        padding: 10px;
    }
    article {
        padding-top: 40px;
        margin: 1%;
    }
    @media (min-width: 800px) {
        article {
            width: 30%;
            float: left;
        }
        footer {
            clear: both;
        }
    }
    @media (max-width: 799px) {
        article {
            width: 98%;
        }
    }
    #book1 {
        background-color: DodgerBlue;
    }
    #book2 {
        background-color: LimeGreen;
    }
    #book3 {
        background-color: DarkOrchid;
    }
    img {
        width: 70%;
    }
    p {
        padding: 20px;
    }
    table {
        margin: auto;
        width: 70%;
        border: 1px solid SteelBlue;
    }
    tr:hover {
        background-color: SteelBlue;
        color: white;
    }
    Podgląd strony po tym kroku (biblioteka.php)
  34. Etap 4: Skrypt PHP

    Kroki 34-38 · po tym etapie masz 36 z 36 kryteriów (pkt)

    Krok 34: Połączenie z bazą danych

    Kryteria: , ,

    R.5.1 Skrypt napisany w języku PHP i zawiera przynajmniej jedną zgodną z treścią zadania instrukcję

    R.5.2 Skrypt realizuje połączenie z serwerem bazy danych i wybór bazy biblioteka

    R.5.6 W skryptach zastosowana przynajmniej jedna zmienna oraz nazwy wszystkich zmiennych są w języku polskim lub angielskim i odzwierciedlają cel zastosowania

    ok. 3 min
    Polecenie z arkusza

    Napisany w języku PHP. Łączy się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie biblioteka.

    Kod PHP piszesz między <?php a ?> - serwer wykonuje go, zanim strona trafi do przeglądarki. Połączenie otwierasz na samym początku pliku i trzymasz w zmiennej $connection (znacząca, angielska nazwa - R.5.6). mysqli_connect z tabeli 1 arkusza przyjmuje kolejno: serwer, użytkownika, hasło (puste) i nazwę bazy.

    Od tego kroku podgląd to wynik działania strony po stronie serwera (PHP nie wykonuje się w przeglądarce) - na razie wygląda jak wcześniej, bo skrypt niczego nie wypisuje.

    Typowe błędy

    Kolejność argumentów ma znaczenie: mysqli_connect('localhost', 'root', 'biblioteka') podaje „biblioteka” jako HASŁO. Nazwa bazy jest czwarta. Plik sprawdzaj przez http://localhost/…, nie otwierając go z dysku - inaczej PHP się nie wykona.

    biblioteka.php PHP zmienione: 3 linie
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'biblioteka');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
            <h3>Nasze dzisiejsze propozycje:</h3>
            <table>
                <tr><th>Autor</th><th>Tytuł</th><th>Katalog</th></tr>
            </table>
        </section>
        <main>
            <article id="book1">
                <img src="ksiazka1.jpg" alt="okładka książki">
                <p>Według różnych podań najpaskudniejsza ropucha nosi w głowie piękny, cenny klejnot.</p>
            </article>
            <article id="book2">
                <img src="ksiazka2.jpg" alt="okładka książki">
                <p>Panna Stefcia i Maryla nie są to zbyt grzeczne damy, nawet nie słuchają mamy...</p>
            </article>
            <article id="book3">
                <img src="ksiazka3.jpg" alt="okładka książki">
                <p>Ratuj mnie, przyjacielu, w ostatniej potrzebie: Kocham piękną Irenę. Rodzice i ona...</p>
            </article>
        </main>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biblioteka.php)
  35. Krok 35: Zapytanie 4 do bazy

    Kryteria:

    R.5.4 Skrypt zawiera instrukcję wysyłającą do bazy danych zapytanie 4

    ok. 2 min
    Polecenie z arkusza

    Wysyła do bazy danych zapytanie 4.

    Skrypt piszesz wewnątrz <table>, pod wierszem nagłówkowym - tam mają trafić wiersze. mysqli_query($connection, ...) wysyła zapytanie i zwraca wynik, który zapisujesz w $books. Treść to dokładnie zapytanie 4 z kwerendy.txt: pięć losowych książek. Kolejność kolumn w SELECT zaraz będzie ważna: $row[0] to autor, $row[1] tytuł, $row[2] kod.

    biblioteka.php PHP zmienione: 3 linie
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'biblioteka');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
            <h3>Nasze dzisiejsze propozycje:</h3>
            <table>
                <tr><th>Autor</th><th>Tytuł</th><th>Katalog</th></tr>
    <?php
    $books = mysqli_query($connection, 'SELECT autor, tytul, kod FROM ksiazki ORDER BY RAND() LIMIT 5;');
    ?>
            </table>
        </section>
        <main>
            <article id="book1">
                <img src="ksiazka1.jpg" alt="okładka książki">
                <p>Według różnych podań najpaskudniejsza ropucha nosi w głowie piękny, cenny klejnot.</p>
            </article>
            <article id="book2">
                <img src="ksiazka2.jpg" alt="okładka książki">
                <p>Panna Stefcia i Maryla nie są to zbyt grzeczne damy, nawet nie słuchają mamy...</p>
            </article>
            <article id="book3">
                <img src="ksiazka3.jpg" alt="okładka książki">
                <p>Ratuj mnie, przyjacielu, w ostatniej potrzebie: Kocham piękną Irenę. Rodzice i ona...</p>
            </article>
        </main>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

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

  36. Krok 36: Pętla po zwróconych wierszach

    Kryteria:

    R.5.5 Skrypt wyświetla w wierszach tabeli dane zwrócone zapytaniem, dane są wpisane do odpowiednich komórek tabeli

    ok. 2 min
    Polecenie z arkusza

    W każdym wierszu tabeli, w odpowiednich komórkach, wyświetlane są zwrócone zapytaniem kolejne wiersze z bazy.

    „Kolejne wiersze” to pętla. mysqli_fetch_row($books) (tabela 1) oddaje kolejny wiersz wyniku jako tablicę numerowaną od zera, a gdy wierszy zabraknie - false. Zapis while ($row = mysqli_fetch_row($books)) przypisuje wiersz do $row i od razu sprawdza, czy coś przyszło - pętla wykona się pięć razy. Ciało jest jeszcze puste.

    Typowe błędy

    Pojedyncze = w warunku while jest tu celowe (przypisanie); == porównałoby zmienną z wynikiem i pętla nie zadziałałaby poprawnie.

    biblioteka.php PHP zmienione: 2 linie
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'biblioteka');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
            <h3>Nasze dzisiejsze propozycje:</h3>
            <table>
                <tr><th>Autor</th><th>Tytuł</th><th>Katalog</th></tr>
    <?php
    $books = mysqli_query($connection, 'SELECT autor, tytul, kod FROM ksiazki ORDER BY RAND() LIMIT 5;');
    while ($row = mysqli_fetch_row($books)) {
    }
    ?>
            </table>
        </section>
        <main>
            <article id="book1">
                <img src="ksiazka1.jpg" alt="okładka książki">
                <p>Według różnych podań najpaskudniejsza ropucha nosi w głowie piękny, cenny klejnot.</p>
            </article>
            <article id="book2">
                <img src="ksiazka2.jpg" alt="okładka książki">
                <p>Panna Stefcia i Maryla nie są to zbyt grzeczne damy, nawet nie słuchają mamy...</p>
            </article>
            <article id="book3">
                <img src="ksiazka3.jpg" alt="okładka książki">
                <p>Ratuj mnie, przyjacielu, w ostatniej potrzebie: Kocham piękną Irenę. Rodzice i ona...</p>
            </article>
        </main>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

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

  37. Krok 37: Wiersz tabeli z trzema komórkami

    Kryteria: ,

    R.5.5 Skrypt wyświetla w wierszach tabeli dane zwrócone zapytaniem, dane są wpisane do odpowiednich komórek tabeli

    R.2.9 W bloku sekcji umieszczono tabelę o 3 kolumnach (w skrypcie lub HTML) zastosowane znaczniki <table>, <tr>, <td>

    ok. 3 min
    Polecenie z arkusza

    W każdym wierszu tabeli, w odpowiednich komórkach, wyświetlane są zwrócone zapytaniem kolejne wiersze z bazy.

    echo w pętli dokłada jeden <tr> z trzema <td>: autor ($row[0]), tytuł ($row[1]), kod ($row[2]) - w tej kolejności, bo tak są ułożone kolumny nagłówkowe Autor, Tytuł, Katalog. Napis w cudzysłowie, żeby PHP podstawił wartości. Klucz R.5.5 sprawdza, że dane są „w odpowiednich komórkach”.

    Podgląd pokazuje pięć książek z ilustracji 2 arkusza; na żywym serwerze każde odświeżenie losuje inne.

    Typowe błędy

    echo '<tr><td>$row[0]</td>...' w apostrofach wypisze dosłownie „$row[0]” - PHP nie podstawia zmiennych w apostrofach.

    biblioteka.php PHP zmienione: 1 linia
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'biblioteka');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
            <h3>Nasze dzisiejsze propozycje:</h3>
            <table>
                <tr><th>Autor</th><th>Tytuł</th><th>Katalog</th></tr>
    <?php
    $books = mysqli_query($connection, 'SELECT autor, tytul, kod FROM ksiazki ORDER BY RAND() LIMIT 5;');
    while ($row = mysqli_fetch_row($books)) {
        echo "<tr><td>$row[0]</td><td>$row[1]</td><td>$row[2]</td></tr>";
    }
    ?>
            </table>
        </section>
        <main>
            <article id="book1">
                <img src="ksiazka1.jpg" alt="okładka książki">
                <p>Według różnych podań najpaskudniejsza ropucha nosi w głowie piękny, cenny klejnot.</p>
            </article>
            <article id="book2">
                <img src="ksiazka2.jpg" alt="okładka książki">
                <p>Panna Stefcia i Maryla nie są to zbyt grzeczne damy, nawet nie słuchają mamy...</p>
            </article>
            <article id="book3">
                <img src="ksiazka3.jpg" alt="okładka książki">
                <p>Ratuj mnie, przyjacielu, w ostatniej potrzebie: Kocham piękną Irenę. Rodzice i ona...</p>
            </article>
        </main>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biblioteka.php)
  38. Krok 38: Zamknięcie połączenia z bazą

    Kryteria:

    R.5.3 Ostatnią operacją na bazie jest jej zamknięcie

    ok. 1 min
    Polecenie z arkusza

    Na końcu działania skrypt zamyka połączenie z serwerem.

    mysqli_close($connection) na końcu pliku, po wszystkich operacjach na bazie. Klucz R.5.3 sprawdza, że zamknięcie jest ostatnią operacją na bazie. Strona spełnia wszystkie kryteria arkusza - dalej trzy kroki „jak w prawdziwym projekcie”.

    biblioteka.php PHP zmienione: 3 linie
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'biblioteka');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
            <h3>Nasze dzisiejsze propozycje:</h3>
            <table>
                <tr><th>Autor</th><th>Tytuł</th><th>Katalog</th></tr>
    <?php
    $books = mysqli_query($connection, 'SELECT autor, tytul, kod FROM ksiazki ORDER BY RAND() LIMIT 5;');
    while ($row = mysqli_fetch_row($books)) {
        echo "<tr><td>$row[0]</td><td>$row[1]</td><td>$row[2]</td></tr>";
    }
    ?>
            </table>
        </section>
        <main>
            <article id="book1">
                <img src="ksiazka1.jpg" alt="okładka książki">
                <p>Według różnych podań najpaskudniejsza ropucha nosi w głowie piękny, cenny klejnot.</p>
            </article>
            <article id="book2">
                <img src="ksiazka2.jpg" alt="okładka książki">
                <p>Panna Stefcia i Maryla nie są to zbyt grzeczne damy, nawet nie słuchają mamy...</p>
            </article>
            <article id="book3">
                <img src="ksiazka3.jpg" alt="okładka książki">
                <p>Ratuj mnie, przyjacielu, w ostatniej potrzebie: Kocham piękną Irenę. Rodzice i ona...</p>
            </article>
        </main>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    <?php
    mysqli_close($connection);
    ?>
    </body>
    </html>

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

  39. Etap 5: Dobre praktyki (poza kluczem)

    Kroki 39-41 · po tym etapie masz 36 z 36 kryteriów (pkt)

    Krok 39: Refaktor: nazwy kolumn zamiast numerów

    Kryteria:

    R.5.5 Skrypt wyświetla w wierszach tabeli dane zwrócone zapytaniem, dane są wpisane do odpowiednich komórek tabeli

    ok. 3 min
    Polecenie z arkusza

    W każdym wierszu tabeli, w odpowiednich komórkach, wyświetlane są zwrócone zapytaniem kolejne wiersze z bazy.

    $row[0], $row[1], $row[2] działa, ale za miesiąc nikt nie pamięta, co było pod którym numerem - a wystarczy zmienić kolejność kolumn w SELECT, żeby tytuł wylądował w kolumnie „Autor”. mysqli_fetch_assoc (tabela 1 wymienia pokrewne mysqli_fetch_array) oddaje wiersz jako tablicę z nazwami kolumn: $row['autor'], $row['tytul'], $row['kod']. Kod czyta się sam.

    W napisie w cudzysłowie element tablicy z kluczem w apostrofach trzeba objąć nawiasami klamrowymi: {$row['autor']}. Stara pętla zostaje w komentarzu // do porównania. Podgląd bez zmian.

    Typowe błędy

    "$row['autor']" bez klamer to błąd składni PHP wewnątrz cudzysłowu - albo klamry {$row['autor']}, albo prosta składnia "$row[autor]" z kluczem bez apostrofów (poprawna tylko wewnątrz napisu w cudzysłowie).

    biblioteka.php PHP zmienione: 5 linii
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'biblioteka');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
            <h3>Nasze dzisiejsze propozycje:</h3>
            <table>
                <tr><th>Autor</th><th>Tytuł</th><th>Katalog</th></tr>
    <?php
    $books = mysqli_query($connection, 'SELECT autor, tytul, kod FROM ksiazki ORDER BY RAND() LIMIT 5;');
    // while ($row = mysqli_fetch_row($books)) {
    //     echo "<tr><td>$row[0]</td><td>$row[1]</td><td>$row[2]</td></tr>";
    // }
    while ($row = mysqli_fetch_assoc($books)) {
        echo "<tr><td>{$row['autor']}</td><td>{$row['tytul']}</td><td>{$row['kod']}</td></tr>";
    }
    ?>
            </table>
        </section>
        <main>
            <article id="book1">
                <img src="ksiazka1.jpg" alt="okładka książki">
                <p>Według różnych podań najpaskudniejsza ropucha nosi w głowie piękny, cenny klejnot.</p>
            </article>
            <article id="book2">
                <img src="ksiazka2.jpg" alt="okładka książki">
                <p>Panna Stefcia i Maryla nie są to zbyt grzeczne damy, nawet nie słuchają mamy...</p>
            </article>
            <article id="book3">
                <img src="ksiazka3.jpg" alt="okładka książki">
                <p>Ratuj mnie, przyjacielu, w ostatniej potrzebie: Kocham piękną Irenę. Rodzice i ona...</p>
            </article>
        </main>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    <?php
    mysqli_close($connection);
    ?>
    </body>
    </html>

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

  40. Krok 40: Refaktor: escapowanie danych przed wypisaniem

    Kryteria:

    R.5.5 Skrypt wyświetla w wierszach tabeli dane zwrócone zapytaniem, dane są wpisane do odpowiednich komórek tabeli

    ok. 3 min
    Polecenie z arkusza

    W każdym wierszu tabeli, w odpowiednich komórkach, wyświetlane są zwrócone zapytaniem kolejne wiersze z bazy.

    Skrypt wypisuje do HTML to, co jest w bazie. W tym arkuszu katalog jest zamknięty, ale w prawdziwej bibliotece tytuły dodają ludzie - tytuł <script>alert(1)</script> wykonałby się w przeglądarce każdego odwiedzającego (XSS). htmlspecialchars() zamienia <, >, ", & na encje, więc tekst wyświetla się dosłownie i nie staje się kodem.

    Każdą wartość przepuszczasz przez htmlspecialchars do osobnej zmiennej o angielskiej nazwie, a echo używa już tylko tych zmiennych. Podgląd wygląda identycznie, bo tytuły z archiwum nie mają znaków specjalnych.

    Typowe błędy

    htmlspecialchars przy zapisie do bazy zamiast przy wypisywaniu to częsty błąd: baza dostaje zniekształcone dane (&amp; zamiast &). Escapujesz na wyjściu, tam gdzie HTML.

    biblioteka.php PHP zmienione: 4 linie
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'biblioteka');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
            <h3>Nasze dzisiejsze propozycje:</h3>
            <table>
                <tr><th>Autor</th><th>Tytuł</th><th>Katalog</th></tr>
    <?php
    $books = mysqli_query($connection, 'SELECT autor, tytul, kod FROM ksiazki ORDER BY RAND() LIMIT 5;');
    // while ($row = mysqli_fetch_row($books)) {
    //     echo "<tr><td>$row[0]</td><td>$row[1]</td><td>$row[2]</td></tr>";
    // }
    while ($row = mysqli_fetch_assoc($books)) {
        $author = htmlspecialchars($row['autor']);
        $title = htmlspecialchars($row['tytul']);
        $code = htmlspecialchars($row['kod']);
        echo "<tr><td>$author</td><td>$title</td><td>$code</td></tr>";
    }
    ?>
            </table>
        </section>
        <main>
            <article id="book1">
                <img src="ksiazka1.jpg" alt="okładka książki">
                <p>Według różnych podań najpaskudniejsza ropucha nosi w głowie piękny, cenny klejnot.</p>
            </article>
            <article id="book2">
                <img src="ksiazka2.jpg" alt="okładka książki">
                <p>Panna Stefcia i Maryla nie są to zbyt grzeczne damy, nawet nie słuchają mamy...</p>
            </article>
            <article id="book3">
                <img src="ksiazka3.jpg" alt="okładka książki">
                <p>Ratuj mnie, przyjacielu, w ostatniej potrzebie: Kocham piękną Irenę. Rodzice i ona...</p>
            </article>
        </main>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    <?php
    mysqli_close($connection);
    ?>
    </body>
    </html>

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

  41. Krok 41: Refaktor: baza na górze, HTML na dole

    Kryteria: , ,

    R.5.2 Skrypt realizuje połączenie z serwerem bazy danych i wybór bazy biblioteka

    R.5.3 Ostatnią operacją na bazie jest jej zamknięcie

    R.5.5 Skrypt wyświetla w wierszach tabeli dane zwrócone zapytaniem, dane są wpisane do odpowiednich komórek tabeli

    ok. 4 min
    Polecenie z arkusza

    Na końcu działania skrypt zamyka połączenie z serwerem.

    Dotąd kod bazy był wpleciony w tabelę, a zamknięcie połączenia stało na końcu pliku, daleko od otwarcia. W prawdziwych projektach całą pracę z bazą robi się na górze pliku, a HTML tylko wyświetla gotowe dane:

    • mysqli_fetch_all($result, MYSQLI_ASSOC) pobiera wszystkie wiersze naraz do tablicy $books,
    • mysqli_close($connection) zaraz po tym - połączenie żyje tylko tyle, ile trzeba, i nadal jest ostatnią operacją na bazie (R.5.3),
    • w tabeli zostaje tylko foreach ($books as $row) z echo - zwykła pętla po tablicy, bez funkcji mysqli_*.

    Gdyby ktoś chciał zmienić bazę na inną (albo wczytać książki z pliku), zmienia tylko górę pliku - tabela nie wie, skąd są dane. Podgląd bez zmian.

    Typowe błędy

    mysqli_fetch_all($result) bez MYSQLI_ASSOC oddaje wiersze z numerami kolumn zamiast nazw - wtedy $row['tytul'] w pętli daje ostrzeżenie „Undefined array key” i pustą komórkę (sprawdzone w PHP 8.2).

    biblioteka.php PHP zmienione: 4 linie
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'biblioteka');
    $result = mysqli_query($connection, 'SELECT autor, tytul, kod FROM ksiazki ORDER BY RAND() LIMIT 5;');
    $books = mysqli_fetch_all($result, MYSQLI_ASSOC);
    mysqli_close($connection);
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>BIBLIOTEKA SZKOLNA</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <header>
            <h2>STRONA BIBLIOTEKI SZKOLNEJ WIEDZAMIN</h2>
        </header>
        <section>
            <h3>Nasze dzisiejsze propozycje:</h3>
            <table>
                <tr><th>Autor</th><th>Tytuł</th><th>Katalog</th></tr>
    <?php
    foreach ($books as $row) {
        $author = htmlspecialchars($row['autor']);
        $title = htmlspecialchars($row['tytul']);
        $code = htmlspecialchars($row['kod']);
        echo "<tr><td>$author</td><td>$title</td><td>$code</td></tr>";
    }
    ?>
            </table>
        </section>
        <main>
            <article id="book1">
                <img src="ksiazka1.jpg" alt="okładka książki">
                <p>Według różnych podań najpaskudniejsza ropucha nosi w głowie piękny, cenny klejnot.</p>
            </article>
            <article id="book2">
                <img src="ksiazka2.jpg" alt="okładka książki">
                <p>Panna Stefcia i Maryla nie są to zbyt grzeczne damy, nawet nie słuchają mamy...</p>
            </article>
            <article id="book3">
                <img src="ksiazka3.jpg" alt="okładka książki">
                <p>Ratuj mnie, przyjacielu, w ostatniej potrzebie: Kocham piękną Irenę. Rodzice i ona...</p>
            </article>
        </main>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

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

  42. Etap 6: Oddanie pracy

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

    Krok 42: 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 weryfikowana była poprawność działania witryny. Nagraj płytę z rezultatami pracy.

    W przeglądarka.txt wpisujesz nazwę przeglądarki, w której sprawdzasz stronę przez http://localhost/….

    W folderze z numerem zdającego muszą być: biblioteka.php, import.png, ksiazka1.jpg, ksiazka2.jpg, ksiazka3.jpg, kw1.png, kw2.png, kw3.png, kw4.png, kwerendy.txt, przeglądarka.txt, styles.css. Nagraj płytę, sprawdź jej odczyt i opisz numerem zdającego. Pusta lub nieczytelna płyta to zero punktów za wszystkie pięć rezultatów.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

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

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.