Przejdź do głównej treści
INF.03-06-24.01-SGStyczeń 2024 · 38 kroków · ok. 73 min · 34 kryteria z klucza

Rozwiązanie krok po kroku: Aplikacja biura podróży (Nowoczesny kod (grid, PDO))

To drugi sposób rozwiązania tego samego arkusza: baza podroze z czterema zapytaniami, strona biuro.php z banerem, trzema blokami obok siebie (promocje, galeria, kontakt), blokiem dawnych wyjazdów i stopką oraz style w styl9.css. Obie wersje spełniają wszystkie 34 kryteria klucza - różni je sposób pisania kodu, nie wynik.

Czym ta wersja różni się od podstawowej:

  • SQL czytelnie: klauzule w osobnych liniach, aliasy tabel w złączeniu (JOIN ... ON), warunek dostepna = FALSE, dawne wyjazdy posortowane po dacie,
  • układ na siatce CSS (display: grid na <body>, kolumny 20% / 60% / 20%) zamiast float i clear, galeria zdjęć na flexboksie, kolory w zmiennych CSS, bloki w znacznikach, które mówią, czym są (header, aside, main, section, footer),
  • PHP na PDO (klucz przyjmuje MySQLi albo PDO): połączenie i oba zapytania na początku pliku biuro.php, w try/catch; w treści strony już tylko pętle foreach, a każdy tekst z bazy przechodzi przez funkcję e() (htmlspecialchars), także w atrybutach alt i title.

Baza i zdjęcia pochodzą z prawdziwego archiwum materialy6 (załącznik do arkusza, hasło w treści zadania). Zapytania są policzone na MariaDB 10.4 - tej samej, która jest w XAMPP. Podgląd strony to wynik prawdziwego uruchomienia kodu z danego kroku w PHP 8.2; najedź na zdjęcie w galerii, a pojawi się dymek z nazwą miasta, jak na obrazie 2. Sprawdzony jest też komunikat przy niedziałającej bazie.

Jak liczą się punkty. Klucz ma 34 kryteria (R.1.1 - R.5.7), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 26 punktów. 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 34 kryteriów (pkt)

    Krok 1: Baza danych podroze

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

    Utwórz bazę danych o nazwie podroze.

    Rozpakuj materialy6.7z z pulpitu (hasło $poDrozE&!) do folderu z numerem zdającego: egzamin.sql i zdjęcia 1.jpg - 9.jpg. W phpMyAdmin: Nowa, nazwa podroze, porównywanie np. utf8mb4_polish_ci.

    Tabele z egzamin.sql mają zestaw znaków zapisany we własnej definicji (latin1), więc wybór dla bazy ich nie zmienia - dane i tak są bez polskich liter („Francja, Paryz”).

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

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

    Do bazy podroze zaimportuj tabele z pliku egzamin.sql z rozpakowanego archiwum.

    Zaznaczona baza podroze, Import → egzamin.sql. W zadaniu potrzebne są dwie tabele z obrazu 1: zdjecia (nazwa pliku i podpis) i wycieczki (cel, data wyjazdu, cena, pole logiczne dostepna i klucz obcy zdjecia_id wskazujący zdjęcie celu).

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

    R.1.1 Wykonano import tabel do bazy danych podroze 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 pod nazwą import. Zrzut powinien obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel.

    Print Screen i zapis jako import.png - import w PNG, a zrzuty zapytań w JPEG (kw1.jpg - kw4.jpg) z widoczną treścią zapytania.

    Typowe błędy

    Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany.

  4. Krok 4: Zapytanie 1: zdjęcia według podpisu

    Kryteria: ,

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

    R.1.3 Wykonano zapytanie 1 wybierające jedynie pola nazwaPliku i podpis z tabeli zdjecia sortując je rosnąco według kolumny podpis. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwaPliku, podpis FROM zdjecia ORDER BY podpis; (opcjonalnie ASC) oraz wynik działania udokumentowano zrzutem, na którym widocznych jest dokładnie 9 rekordów dla kolejnych nazw plików 8, 3, 5, 1, 9, 7, 6, 4, 2, jedynie pola nazwaPliku i podpis

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 1: wybierające jedynie pola nazwaPliku i podpis z tabeli zdjecia sortując je rosnąco według kolumny podpis.

    • SELECT nazwaPliku, podpis / FROM zdjecia - dwie kolumny,
    • ORDER BY podpis - rosnąco, czyli alfabetycznie; ASC jest domyślne.

    Wynik: 9 zdjęć w kolejności plików 8, 3, 5, 1, 9, 7, 6, 4, 2 - od Barcelony do Wenecji (R.1.3). Zapytanie do kwerendy.txt, zrzut kw1.jpg. To zapytanie wyśle Skrypt 1 - w tej kolejności stanie galeria.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT nazwaPliku, podpis
    FROM zdjecia
    ORDER BY podpis;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: wycieczki niedostępne

    Kryteria:

    R.1.4 Wykonano zapytanie 2 wybierające jedynie pola cel i dataWyjazdu z tabeli wycieczki dla wycieczek, które nie są dostępne. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT cel, dataWyjazdu FROM wycieczki WHERE dostepna = FALSE; (lub =0) oraz wynik działania udokumentowano zrzutem, na którym widoczne są dokładnie 3 rekordy: Francja, Paryz, 2019-07-14; Hiszpania, Barcelona 2019-07-14; Hiszpania, Barcelona 2019-08-14;

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 2: wybierające jedynie pola cel i dataWyjazdu z tabeli wycieczki dla wycieczek, które nie są dostępne.

    • WHERE dostepna = FALSE - pole logiczne (tinyint(1)) przechowuje fałsz jako 0; słowo FALSE mówi wprost, o co chodzi, i daje ten sam wynik co = 0,
    • ORDER BY dataWyjazdu, cel - wyjazdy od najdawniejszego; przy tej samej dacie decyduje cel. Arkusz kolejności nie podaje, ale lista „W poprzednich latach byliśmy...” czyta się w porządku dat.

    Wynik: 3 wycieczki - Paryż 2019-07-14 oraz Barcelona 2019-07-14 i 2019-08-14, w tej samej kolejności co w kluczu (R.1.4). Zrzut kw2.jpg. To zapytanie wyśle Skrypt 2.

    kwerendy.txt Tekst zmienione: 6 linii
    -- Zapytanie 1
    SELECT nazwaPliku, podpis
    FROM zdjecia
    ORDER BY podpis;
    
    -- Zapytanie 2
    SELECT cel, dataWyjazdu
    FROM wycieczki
    WHERE dostepna = FALSE
    ORDER BY dataWyjazdu, cel;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: drogie wycieczki z podpisem zdjęcia

    Kryteria:

    R.1.5 Wykonano zapytanie 3 wybierające jedynie pola cel i cena z tabeli wycieczki oraz odpowiadające im pole podpis z tabeli zdjecia , dla wycieczek, których cena jest wyższa niż 1300 zł. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT cel, cena, podpis FROM zdjecia JOIN wycieczki ON zdjecia.id = wycieczki.zdjecia_id WHERE cena > 1300; (możliwe też INNER JOIN lub porównanie kluczy po WHERE) oraz wynik działania udokumentowano zrzutem, na którym widoczne są dokładnie 4 rekordy: Francja, Paryz 1350 Paryz; Hiszpania, Barcelona 1500 Barcelona; Hiszpania, Barcelona 1500 Barcelona; Hiszpania, Barcelona 1400 Barcelona;

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie pola cel i cena z tabeli wycieczki oraz odpowiadające im pole podpis z tabeli zdjecia, dla wycieczek, których cena jest wyższa niż 1300 zł. Zapytanie wykorzystuje relację.

    • FROM wycieczki AS w / JOIN zdjecia AS z - aliasy tabel, krótkie nazwy używane w całym zapytaniu. Przy złączeniu każda kolumna dostaje przedrostek swojej tabeli (w.cena, z.podpis) i od razu widać, skąd pochodzi,
    • ON z.id = w.zdjecia_id - relacja: wycieczka dostaje zdjęcie, na które wskazuje jej klucz obcy,
    • WHERE w.cena > 1300 - „wyższa niż”, więc Paryż za równe 1300 zł nie wchodzi.

    Wynik: 4 wiersze - Paryż 1350 i trzy razy Barcelona (1500, 1500, 1400), każdy z podpisem swojego zdjęcia (R.1.5). Zrzut kw3.jpg.

    Typowe błędy

    FROM wycieczki, zdjecia bez warunku łączącego daje iloczyn kartezjański - każdą wycieczkę z każdym zdjęciem.

    kwerendy.txt Tekst zmienione: 6 linii
    -- Zapytanie 1
    SELECT nazwaPliku, podpis
    FROM zdjecia
    ORDER BY podpis;
    
    -- Zapytanie 2
    SELECT cel, dataWyjazdu
    FROM wycieczki
    WHERE dostepna = FALSE
    ORDER BY dataWyjazdu, cel;
    
    -- Zapytanie 3
    SELECT w.cel, w.cena, z.podpis
    FROM wycieczki AS w
    JOIN zdjecia AS z ON z.id = w.zdjecia_id
    WHERE w.cena > 1300;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: usunięcie tabeli uzytkownik

    Kryteria:

    R.1.6 Wykonano zapytanie 4 usuwające tabelę uzytkownik . W pliku z kwerendami lub na zrzucie istnieje zapis np.: DROP TABLE uzytkownik; oraz wynik działania udokumentowano zrzutem, na którym widnieje komunikat o poprawnym usunięciu lub spis tabel bazy danych bez tabeli uzytkownik

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 4: usuwające tabelę uzytkownik.

    DROP TABLE usuwa całą tabelę - strukturę i dane; DELETE skasowałby tylko wiersze. phpMyAdmin pyta o potwierdzenie (R.1.6).

    Sprawdzone na bazie: przed zapytaniem tabele to kadra, matematycy, typy, uslugi, uzytkownik, wycieczki, wyniki, zdjecia, po nim zostają kadra, matematycy, typy, uslugi, wycieczki, wyniki, zdjecia. Zrzut kw4.jpg - komunikat albo lista tabel bez uzytkownik.

    Typowe błędy

    DELETE FROM uzytkownik opróżnia tabelę, ale jej nie usuwa - to nie spełnia R.1.6.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT nazwaPliku, podpis
    FROM zdjecia
    ORDER BY podpis;
    
    -- Zapytanie 2
    SELECT cel, dataWyjazdu
    FROM wycieczki
    WHERE dostepna = FALSE
    ORDER BY dataWyjazdu, cel;
    
    -- Zapytanie 3
    SELECT w.cel, w.cena, z.podpis
    FROM wycieczki AS w
    JOIN zdjecia AS z ON z.id = w.zdjecia_id
    WHERE w.cena > 1300;
    
    -- Zapytanie 4
    DROP TABLE uzytkownik;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Strona HTML

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

    Krok 8: Plik biuro.php w HTML5

    Kryteria: ,

    R.2.1 Witrynę internetową zapisano w pliku PHP o nazwie biuro

    R.2.2 Zastosowano deklarację języka HTML5 <!DOCTYPE html>, zadeklarowano język witryny polski np. <html lang = "pl"> oraz zapisano jawnie właściwy standard kodowania polskich znaków

    ok. 1 min
    Polecenie z arkusza

    Cechy witryny: Składa się ze strony o nazwie biuro.php zapisanej w języku HTML 5.

    Jedna strona, biuro.php (R.2.1, R.2.2). Dopóki nie ma w niej kodu PHP, podgląd pokazuje ją wprost. Zdjęcia 1.jpg - 9.jpg leżą obok strony.

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

    Kryteria:

    R.2.2 Zastosowano deklarację języka HTML5 <!DOCTYPE html>, zadeklarowano język witryny polski np. <html lang = "pl"> oraz zapisano jawnie właściwy standard kodowania polskich znaków

    ok. 1 min
    Polecenie z arkusza

    Ustawiony język zawartości strony na polski.

    Atrybut lang="pl" w <html>.

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

    Kryteria:

    R.2.2 Zastosowano deklarację języka HTML5 <!DOCTYPE html>, zadeklarowano język witryny polski np. <html lang = "pl"> oraz zapisano jawnie właściwy 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"> (R.2.2), pod nim <meta name="viewport"> - telefon pokaże stronę w swojej szerokości. Arkusz drugiej linii nie wymaga.

    biuro.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (biuro.php)
  11. Krok 11: Tytuł strony

    Kryteria:

    R.2.3 Stronie nadano tytuł: "Poznaj Europę"

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Poznaj Europę”.

    <title> w <head>.

    biuro.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (biuro.php)
  12. Krok 12: Podpięcie arkusza stylów

    Kryteria:

    R.3.3 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl9.css , formatowanie CSS 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 styl9.css prawidłowo połączony z kodem strony.

    Nazwa z cyfrą: styl9.css.

    Typowe błędy

    styl.css bez dziewiątki odcina wszystkie style (R.3.3).

    biuro.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
        <link rel="stylesheet" href="styl9.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (biuro.php)
  13. Krok 13: Bloki strony

    Kryteria:

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

    ok. 3 min
    Polecenie z arkusza

    Podział strony na bloki: na górze baner, poniżej obok siebie trzy bloki: lewy, środkowy i prawy, poniżej blok z danymi, poniżej stopka. 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.

    Każdy blok w znaczniku, który mówi, czym jest (R.2.4):

    • baner - <header>,
    • blok środkowy z galerią - <main class="gallery">, treść główna strony,
    • bloki lewy (promocje) i prawy (kontakt) - dwa <aside>, treści poboczne obok głównej,
    • blok z danymi o dawnych wyjazdach - <section class="history">,
    • stopka - <footer>.

    Bloki dostają klasy z nazwą treści, a nie położenia (promotions, a nie left): jeśli kiedyś promocje przejdą na prawą stronę, nazwa w kodzie nadal będzie prawdziwa.

    biuro.php PHP zmienione: 12 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
        <link rel="stylesheet" href="styl9.css">
    </head>
    <body>
        <header>
        </header>
        <aside class="promotions">
        </aside>
        <main class="gallery">
        </main>
        <aside class="contact">
        </aside>
        <section class="history">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biuro.php)
  14. Krok 14: Baner

    Kryteria:

    R.2.5 W banerze zapisano nagłówek h1: "BIURO PODRÓŻY", w blokach lewym, środkowym i prawym przynajmniej jeden h2 z: "Promocje", "W tym roku jedziemy do...", "Kontakt", w bloku dane h3: "W poprzednich latach byliśmy..." oraz przynajmniej jeden paragraf

    ok. 1 min
    Polecenie z arkusza

    Zawartość banera: nagłówek pierwszego stopnia o treści: „BIURO PODRÓŻY”.

    <h1> (R.2.5).

    biuro.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
        <link rel="stylesheet" href="styl9.css">
    </head>
    <body>
        <header>
            <h1>BIURO PODRÓŻY</h1>
        </header>
        <aside class="promotions">
        </aside>
        <main class="gallery">
        </main>
        <aside class="contact">
        </aside>
        <section class="history">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biuro.php)
  15. Krok 15: Blok lewy: promocje w tabeli

    Kryteria: ,

    R.2.5 W banerze zapisano nagłówek h1: "BIURO PODRÓŻY", w blokach lewym, środkowym i prawym przynajmniej jeden h2 z: "Promocje", "W tym roku jedziemy do...", "Kontakt", w bloku dane h3: "W poprzednich latach byliśmy..." oraz przynajmniej jeden paragraf

    R.2.7 W bloku lewym zapisano tabelę o 2 kolumnach i 3 wierszach, zastosowano znaczniki <table>, <tr>, <td>

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloku lewego: Nagłówek drugiego stopnia o treści: „Promocje”. Tabela o dwóch kolumnach i trzech wierszach, wypełniona danymi: Warszawa od 600 zł, Wenecja od 1200 zł, Paryż od 1200 zł.

    <h2> i tabela 3 × 2: trzy <tr>, w każdym dwie komórki <td> (R.2.5, R.2.7). Bez wiersza nagłówkowego - arkusz go nie przewiduje, a obraz 2 go nie pokazuje.

    biuro.php PHP zmienione: 15 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
        <link rel="stylesheet" href="styl9.css">
    </head>
    <body>
        <header>
            <h1>BIURO PODRÓŻY</h1>
        </header>
        <aside class="promotions">
            <h2>Promocje</h2>
            <table>
                <tr>
                    <td>Warszawa</td>
                    <td>od 600 zł</td>
                </tr>
                <tr>
                    <td>Wenecja</td>
                    <td>od 1200 zł</td>
                </tr>
                <tr>
                    <td>Paryż</td>
                    <td>od 1200 zł</td>
                </tr>
            </table>
        </aside>
        <main class="gallery">
        </main>
        <aside class="contact">
        </aside>
        <section class="history">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biuro.php)
  16. Krok 16: Blok środkowy: nagłówek

    Kryteria:

    R.2.5 W banerze zapisano nagłówek h1: "BIURO PODRÓŻY", w blokach lewym, środkowym i prawym przynajmniej jeden h2 z: "Promocje", "W tym roku jedziemy do...", "Kontakt", w bloku dane h3: "W poprzednich latach byliśmy..." oraz przynajmniej jeden paragraf

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku środkowego: Nagłówek drugiego stopnia o treści: „W tym roku jedziemy do...”. Efekt działania skryptu 1.

    <h2>; pod nim Skrypt 1 wstawi galerię zdjęć (R.2.5).

    biuro.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
        <link rel="stylesheet" href="styl9.css">
    </head>
    <body>
        <header>
            <h1>BIURO PODRÓŻY</h1>
        </header>
        <aside class="promotions">
            <h2>Promocje</h2>
            <table>
                <tr>
                    <td>Warszawa</td>
                    <td>od 600 zł</td>
                </tr>
                <tr>
                    <td>Wenecja</td>
                    <td>od 1200 zł</td>
                </tr>
                <tr>
                    <td>Paryż</td>
                    <td>od 1200 zł</td>
                </tr>
            </table>
        </aside>
        <main class="gallery">
            <h2>W tym roku jedziemy do...</h2>
        </main>
        <aside class="contact">
        </aside>
        <section class="history">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biuro.php)
  17. Krok 17: Blok prawy: kontakt

    Kryteria: ,

    R.2.5 W banerze zapisano nagłówek h1: "BIURO PODRÓŻY", w blokach lewym, środkowym i prawym przynajmniej jeden h2 z: "Promocje", "W tym roku jedziemy do...", "Kontakt", w bloku dane h3: "W poprzednich latach byliśmy..." oraz przynajmniej jeden paragraf

    R.3.2 Na stronie umieszczono odnośnik "napisz do nas" łączący z adresem [email protected] (href="mailto:[email protected]")

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloku prawego: Nagłówek drugiego stopnia o treści: „Kontakt”. Odnośnik do adresu e-mail [email protected] o treści: „napisz do nas”. Paragraf (akapit) o treści „telefon: 444555666”.

    • odnośnik z przedrostkiem mailto: otwiera program pocztowy z gotowym adresatem (R.3.2),
    • akapit ma treść z arkusza, a sam numer jest odnośnikiem tel: - na telefonie dotknięcie numeru rozpoczyna połączenie. W href numer z kierunkowym kraju (+48), widoczny tekst zostaje jak w arkuszu (R.2.5).
    Typowe błędy

    href="[email protected]" bez mailto: przeglądarka traktuje jak plik w bieżącym folderze.

    biuro.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
        <link rel="stylesheet" href="styl9.css">
    </head>
    <body>
        <header>
            <h1>BIURO PODRÓŻY</h1>
        </header>
        <aside class="promotions">
            <h2>Promocje</h2>
            <table>
                <tr>
                    <td>Warszawa</td>
                    <td>od 600 zł</td>
                </tr>
                <tr>
                    <td>Wenecja</td>
                    <td>od 1200 zł</td>
                </tr>
                <tr>
                    <td>Paryż</td>
                    <td>od 1200 zł</td>
                </tr>
            </table>
        </aside>
        <main class="gallery">
            <h2>W tym roku jedziemy do...</h2>
        </main>
        <aside class="contact">
            <h2>Kontakt</h2>
            <a href="mailto:[email protected]">napisz do nas</a>
            <p>telefon: <a href="tel:+48444555666">444555666</a></p>
        </aside>
        <section class="history">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biuro.php)
  18. Krok 18: Blok z danymi: nagłówek i lista

    Kryteria:

    R.2.5 W banerze zapisano nagłówek h1: "BIURO PODRÓŻY", w blokach lewym, środkowym i prawym przynajmniej jeden h2 z: "Promocje", "W tym roku jedziemy do...", "Kontakt", w bloku dane h3: "W poprzednich latach byliśmy..." oraz przynajmniej jeden paragraf

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku z danymi: Nagłówek trzeciego stopnia o treści: „W poprzednich latach byliśmy...”. Lista numerowana (uporządkowana), a w niej efekt działania skryptu 2.

    <h3> i pusta lista <ol> - elementy <li> wypisze Skrypt 2 (R.2.5).

    biuro.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
        <link rel="stylesheet" href="styl9.css">
    </head>
    <body>
        <header>
            <h1>BIURO PODRÓŻY</h1>
        </header>
        <aside class="promotions">
            <h2>Promocje</h2>
            <table>
                <tr>
                    <td>Warszawa</td>
                    <td>od 600 zł</td>
                </tr>
                <tr>
                    <td>Wenecja</td>
                    <td>od 1200 zł</td>
                </tr>
                <tr>
                    <td>Paryż</td>
                    <td>od 1200 zł</td>
                </tr>
            </table>
        </aside>
        <main class="gallery">
            <h2>W tym roku jedziemy do...</h2>
        </main>
        <aside class="contact">
            <h2>Kontakt</h2>
            <a href="mailto:[email protected]">napisz do nas</a>
            <p>telefon: <a href="tel:+48444555666">444555666</a></p>
        </aside>
        <section class="history">
            <h3>W poprzednich latach byliśmy...</h3>
            <ol>
            </ol>
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biuro.php)
  19. Krok 19: Stopka

    ok. 1 min
    Polecenie z arkusza

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

    Akapit w stopce. Na egzaminie po dwukropku wpisujesz swój numer zdającego (PESEL); tu stoi autor rozwiązania.

    biuro.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
        <link rel="stylesheet" href="styl9.css">
    </head>
    <body>
        <header>
            <h1>BIURO PODRÓŻY</h1>
        </header>
        <aside class="promotions">
            <h2>Promocje</h2>
            <table>
                <tr>
                    <td>Warszawa</td>
                    <td>od 600 zł</td>
                </tr>
                <tr>
                    <td>Wenecja</td>
                    <td>od 1200 zł</td>
                </tr>
                <tr>
                    <td>Paryż</td>
                    <td>od 1200 zł</td>
                </tr>
            </table>
        </aside>
        <main class="gallery">
            <h2>W tym roku jedziemy do...</h2>
        </main>
        <aside class="contact">
            <h2>Kontakt</h2>
            <a href="mailto:[email protected]">napisz do nas</a>
            <p>telefon: <a href="tel:+48444555666">444555666</a></p>
        </aside>
        <section class="history">
            <h3>W poprzednich latach byliśmy...</h3>
            <ol>
            </ol>
        </section>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biuro.php)
  20. Etap 3: Styl CSS

    Kroki 20-29 · po tym etapie masz 25 z 34 kryteriów (pkt)

    Krok 20: Plik styl9.css: kolory z arkusza w zmiennych

    ok. 2 min
    Polecenie z arkusza

    Styl CSS zdefiniowany w całości w zewnętrznym pliku o nazwie styl9.css.

    Kolory arkusza jako zmienne CSS w :root: ciemny róż banera i stopki, róż bloków bocznych, MistyRose bloku środkowego i bloku z danymi, Maroon ramki i pierwszych liter. Reguły odwołują się do nich przez var(--nazwa). Sama definicja nic nie zmienia na stronie.

    styl9.css CSS nowy plik
    :root {
        --color-dark: #BA6B6C;
        --color-side: #EF9A9A;
        --color-light: MistyRose;
        --color-accent: Maroon;
    }
    Podgląd strony po tym kroku (biuro.php)
  21. Krok 21: Czcionka i wyśrodkowanie

    Kryteria:

    R.4.1 Ustawiono domyślne formatowanie wszystkich selektorów (*): krój czcionki Georgia, wyrównanie tekstu do środka

    ok. 1 min
    Polecenie z arkusza

    Ustawione domyślne wartości dla wszystkich selektorów stylu CSS: krój czcionki Georgia, wyrównanie tekstu do środka.

    Selektor uniwersalny * (R.4.1), po kroju Georgia rodzina ogólna serif.

    styl9.css CSS zmienione: 5 linii
    :root {
        --color-dark: #BA6B6C;
        --color-side: #EF9A9A;
        --color-light: MistyRose;
        --color-accent: Maroon;
    }
    
    * {
        font-family: Georgia, serif;
        text-align: center;
    }
    Podgląd strony po tym kroku (biuro.php)
  22. Krok 22: Baner i stopka

    Kryteria: , ,

    R.4.2 Ustawiono kolor tła #BA6B6C dla banera i stopki, #EF9A9A dla bloku lewego i prawego, MistyRose dla bloku z danymi i środkowego

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

    R.4.6 Ustawiono marginesy wewnętrzne (padding) 7px dla banera i stopki, 50px dla bloku z danymi, marginesy zewnętrzne (margin) 7px dla obrazu oraz auto dla tabeli

    ok. 1 min
    Polecenie z arkusza

    Wspólne dla banera i stopki: kolor tła #BA6B6C, biały kolor czcionki, marginesy wewnętrzne 7 px.

    Jedna reguła dla dwóch znaczników (R.4.2, R.4.3, R.4.6).

    styl9.css CSS zmienione: 7 linii
    :root {
        --color-dark: #BA6B6C;
        --color-side: #EF9A9A;
        --color-light: MistyRose;
        --color-accent: Maroon;
    }
    
    * {
        font-family: Georgia, serif;
        text-align: center;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        padding: 7px;
    }
    Podgląd strony po tym kroku (biuro.php)
  23. Krok 23: Bloki lewy, środkowy i prawy

    Kryteria: ,

    R.4.2 Ustawiono kolor tła #BA6B6C dla banera i stopki, #EF9A9A dla bloku lewego i prawego, MistyRose dla bloku z danymi i środkowego

    R.4.5 Ustawiono wysokość 500px dla bloków lewego, środkowego i prawego i 120px dla selektora img

    ok. 2 min
    Polecenie z arkusza

    Dla bloku lewego i prawego: kolor tła #EF9A9A, szerokość 20%, wysokość 500 px. Dla bloku środkowego: kolor tła MistyRose, szerokość 60%, wysokość 500 px.

    Kolory i wysokość 500px (R.4.2, R.4.5). Szerokości 20%, 60% i 20% wpisze siatka w następnym kroku.

    styl9.css CSS zmienione: 11 linii
    :root {
        --color-dark: #BA6B6C;
        --color-side: #EF9A9A;
        --color-light: MistyRose;
        --color-accent: Maroon;
    }
    
    * {
        font-family: Georgia, serif;
        text-align: center;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        padding: 7px;
    }
    
    .promotions,
    .contact {
        background-color: var(--color-side);
        height: 500px;
    }
    
    .gallery {
        background-color: var(--color-light);
        height: 500px;
    }
    Podgląd strony po tym kroku (biuro.php)
  24. Krok 24: Układ: siatka 20% / 60% / 20%

    Kryteria: ,

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

    R.4.4 Ustawiono szerokość 20% dla bloków lewego i prawego, 60% dla środkowego (width lub grid-template-columns lub flex), 80% dla selektora table

    ok. 3 min
    Polecenie z arkusza

    Podział strony na bloki: na górze baner, poniżej obok siebie trzy bloki: lewy, środkowy i prawy, poniżej blok z danymi, poniżej stopka.

    <body> staje się siatką o trzech kolumnach: 20%, 60%, 20% - szerokości z arkusza, zapisane w grid-template-columns (klucz to przyjmuje, R.4.4).

    grid-template-areas rysuje plan z obrazu 2: baner przez całą szerokość, pod nim promocje, galeria i kontakt, potem dawne wyjazdy i stopka - też na całą szerokość. W wersji podstawowej ten sam układ dają float: left na trzech blokach i clear: both w bloku z danymi (R.3.1).

    Typowe błędy

    Szerokości bloków w siatce wpisuj tylko w grid-template-columns. Dodatkowe width: 60% w galerii liczyłoby się od jej kolumny - galeria zajęłaby 36% strony.

    styl9.css CSS zmienione: 17 linii
    :root {
        --color-dark: #BA6B6C;
        --color-side: #EF9A9A;
        --color-light: MistyRose;
        --color-accent: Maroon;
    }
    
    * {
        font-family: Georgia, serif;
        text-align: center;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        padding: 7px;
    }
    
    .promotions,
    .contact {
        background-color: var(--color-side);
        height: 500px;
    }
    
    .gallery {
        background-color: var(--color-light);
        height: 500px;
    }
    
    body {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        grid-template-areas:
            "header     header  header"
            "promotions gallery contact"
            "history    history history"
            "footer     footer  footer";
    }
    
    header      { grid-area: header; }
    .promotions { grid-area: promotions; }
    .gallery    { grid-area: gallery; }
    .contact    { grid-area: contact; }
    .history    { grid-area: history; }
    footer      { grid-area: footer; }
    Podgląd strony po tym kroku (biuro.php)
  25. Krok 25: Blok z danymi

    Kryteria: ,

    R.4.2 Ustawiono kolor tła #BA6B6C dla banera i stopki, #EF9A9A dla bloku lewego i prawego, MistyRose dla bloku z danymi i środkowego

    R.4.6 Ustawiono marginesy wewnętrzne (padding) 7px dla banera i stopki, 50px dla bloku z danymi, marginesy zewnętrzne (margin) 7px dla obrazu oraz auto dla tabeli

    ok. 1 min
    Polecenie z arkusza

    Dla bloku z danymi: kolor tła MistyRose, marginesy wewnętrzne 50 px.

    Klasa .history (R.4.2, R.4.6).

    styl9.css CSS zmienione: 5 linii
    :root {
        --color-dark: #BA6B6C;
        --color-side: #EF9A9A;
        --color-light: MistyRose;
        --color-accent: Maroon;
    }
    
    * {
        font-family: Georgia, serif;
        text-align: center;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        padding: 7px;
    }
    
    .promotions,
    .contact {
        background-color: var(--color-side);
        height: 500px;
    }
    
    .gallery {
        background-color: var(--color-light);
        height: 500px;
    }
    
    body {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        grid-template-areas:
            "header     header  header"
            "promotions gallery contact"
            "history    history history"
            "footer     footer  footer";
    }
    
    header      { grid-area: header; }
    .promotions { grid-area: promotions; }
    .gallery    { grid-area: gallery; }
    .contact    { grid-area: contact; }
    .history    { grid-area: history; }
    footer      { grid-area: footer; }
    
    .history {
        background-color: var(--color-light);
        padding: 50px;
    }
    Podgląd strony po tym kroku (biuro.php)
  26. Krok 26: Lista z cyframi rzymskimi

    Kryteria:

    R.4.7 Ustawiono dla selektora ol punktor wielka cyfra rzymska (list-style lub list-style-type: upper- roman;) oraz dla selektora li wyrównanie tekstu do lewej strony

    ok. 1 min
    Polecenie z arkusza

    Dla selektora listy numerowanej: punktor jest wielką cyfrą rzymską. Dla selektora elementu listy: wyrównanie tekstu do lewej strony.

    Selektory znaczników ol i li - arkusz zastrzega, że styl ma być zdefiniowany wyłącznie nimi (R.4.7). Wielkie cyfry rzymskie to upper-roman.

    Typowe błędy

    Styl dla .history ol albo klasy nie spełnia R.4.7 - klucz uznaje tylko selektory znaczników.

    styl9.css CSS zmienione: 8 linii
    :root {
        --color-dark: #BA6B6C;
        --color-side: #EF9A9A;
        --color-light: MistyRose;
        --color-accent: Maroon;
    }
    
    * {
        font-family: Georgia, serif;
        text-align: center;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        padding: 7px;
    }
    
    .promotions,
    .contact {
        background-color: var(--color-side);
        height: 500px;
    }
    
    .gallery {
        background-color: var(--color-light);
        height: 500px;
    }
    
    body {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        grid-template-areas:
            "header     header  header"
            "promotions gallery contact"
            "history    history history"
            "footer     footer  footer";
    }
    
    header      { grid-area: header; }
    .promotions { grid-area: promotions; }
    .gallery    { grid-area: gallery; }
    .contact    { grid-area: contact; }
    .history    { grid-area: history; }
    footer      { grid-area: footer; }
    
    .history {
        background-color: var(--color-light);
        padding: 50px;
    }
    
    ol {
        list-style-type: upper-roman;
    }
    
    li {
        text-align: left;
    }
    Podgląd strony po tym kroku (biuro.php)
  27. Krok 27: Pierwsza litera nagłówków

    Kryteria:

    R.4.10 Ustawiono styl pseudoelementu h2::first-letter: rozmiar czcionki 170%, kolor czcionki Maroon

    ok. 1 min
    Polecenie z arkusza

    Dla pierwszej litery nagłówka drugiego stopnia: rozmiar czcionki 170%, kolor czcionki Maroon.

    Pseudoelement ::first-letter wybiera samą pierwszą literę - stąd duże „P”, „W”, „K” na obrazie 2, bez dodatkowych znaczników (R.4.10).

    styl9.css CSS zmienione: 5 linii
    :root {
        --color-dark: #BA6B6C;
        --color-side: #EF9A9A;
        --color-light: MistyRose;
        --color-accent: Maroon;
    }
    
    * {
        font-family: Georgia, serif;
        text-align: center;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        padding: 7px;
    }
    
    .promotions,
    .contact {
        background-color: var(--color-side);
        height: 500px;
    }
    
    .gallery {
        background-color: var(--color-light);
        height: 500px;
    }
    
    body {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        grid-template-areas:
            "header     header  header"
            "promotions gallery contact"
            "history    history history"
            "footer     footer  footer";
    }
    
    header      { grid-area: header; }
    .promotions { grid-area: promotions; }
    .gallery    { grid-area: gallery; }
    .contact    { grid-area: contact; }
    .history    { grid-area: history; }
    footer      { grid-area: footer; }
    
    .history {
        background-color: var(--color-light);
        padding: 50px;
    }
    
    ol {
        list-style-type: upper-roman;
    }
    
    li {
        text-align: left;
    }
    
    h2::first-letter {
        font-size: 170%;
        color: var(--color-accent);
    }
    Podgląd strony po tym kroku (biuro.php)
  28. Krok 28: Tabela

    Kryteria: , ,

    R.4.4 Ustawiono szerokość 20% dla bloków lewego i prawego, 60% dla środkowego (width lub grid-template-columns lub flex), 80% dla selektora table

    R.4.6 Ustawiono marginesy wewnętrzne (padding) 7px dla banera i stopki, 50px dla bloku z danymi, marginesy zewnętrzne (margin) 7px dla obrazu oraz auto dla tabeli

    R.4.8 Ustawiono obramowanie dla tabeli: 1px solid Maroon

    ok. 1 min
    Polecenie z arkusza

    Dla selektora tabeli: marginesy zewnętrzne automatycznie wyliczane przez przeglądarkę, szerokość 80%, obramowanie linią ciągłą o szerokości 1 px i kolorze Maroon.

    Selektor table (R.4.4, R.4.6, R.4.8). Ramkę ma tylko tabela, komórki nie - na obrazie 2 widać jedną ramkę wokół całości.

    styl9.css CSS zmienione: 6 linii
    :root {
        --color-dark: #BA6B6C;
        --color-side: #EF9A9A;
        --color-light: MistyRose;
        --color-accent: Maroon;
    }
    
    * {
        font-family: Georgia, serif;
        text-align: center;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        padding: 7px;
    }
    
    .promotions,
    .contact {
        background-color: var(--color-side);
        height: 500px;
    }
    
    .gallery {
        background-color: var(--color-light);
        height: 500px;
    }
    
    body {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        grid-template-areas:
            "header     header  header"
            "promotions gallery contact"
            "history    history history"
            "footer     footer  footer";
    }
    
    header      { grid-area: header; }
    .promotions { grid-area: promotions; }
    .gallery    { grid-area: gallery; }
    .contact    { grid-area: contact; }
    .history    { grid-area: history; }
    footer      { grid-area: footer; }
    
    .history {
        background-color: var(--color-light);
        padding: 50px;
    }
    
    ol {
        list-style-type: upper-roman;
    }
    
    li {
        text-align: left;
    }
    
    h2::first-letter {
        font-size: 170%;
        color: var(--color-accent);
    }
    
    table {
        margin: auto;
        width: 80%;
        border: 1px solid var(--color-accent);
    }
    Podgląd strony po tym kroku (biuro.php)
  29. Krok 29: Obrazy z cieniem i galeria

    Kryteria: , ,

    R.4.5 Ustawiono wysokość 500px dla bloków lewego, środkowego i prawego i 120px dla selektora img

    R.4.6 Ustawiono marginesy wewnętrzne (padding) 7px dla banera i stopki, 50px dla bloku z danymi, marginesy zewnętrzne (margin) 7px dla obrazu oraz auto dla tabeli

    R.4.9 Ustawiono dla obrazu cień box-shadow: 7px 7px 7px DimGray;

    ok. 2 min
    Polecenie z arkusza

    Dla selektora obrazu: wysokość 120 px, marginesy zewnętrzne 7 px, cień o przesunięciu 7 px w obu osiach, rozmyciu 7 px i kolorze DimGray.

    • selektor img: wysokość 120px (szerokość dobiera przeglądarka z proporcji), margines 7px, cień box-shadow: 7px 7px 7px DimGray - przesunięcie poziome, pionowe, rozmycie, kolor (R.4.5, R.4.6, R.4.9),
    • .photos - pojemnik na zdjęcia galerii (powstanie w Skrypcie 1) jako flexbox z zawijaniem i wyśrodkowaniem. Zdjęcia w zwykłej linii tekstu miałyby między sobą dodatkową szparę ze spacji w kodzie HTML; we flexboksie odstęp to wyłącznie marginesy z arkusza.
    styl9.css CSS zmienione: 12 linii
    :root {
        --color-dark: #BA6B6C;
        --color-side: #EF9A9A;
        --color-light: MistyRose;
        --color-accent: Maroon;
    }
    
    * {
        font-family: Georgia, serif;
        text-align: center;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        padding: 7px;
    }
    
    .promotions,
    .contact {
        background-color: var(--color-side);
        height: 500px;
    }
    
    .gallery {
        background-color: var(--color-light);
        height: 500px;
    }
    
    body {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        grid-template-areas:
            "header     header  header"
            "promotions gallery contact"
            "history    history history"
            "footer     footer  footer";
    }
    
    header      { grid-area: header; }
    .promotions { grid-area: promotions; }
    .gallery    { grid-area: gallery; }
    .contact    { grid-area: contact; }
    .history    { grid-area: history; }
    footer      { grid-area: footer; }
    
    .history {
        background-color: var(--color-light);
        padding: 50px;
    }
    
    ol {
        list-style-type: upper-roman;
    }
    
    li {
        text-align: left;
    }
    
    h2::first-letter {
        font-size: 170%;
        color: var(--color-accent);
    }
    
    table {
        margin: auto;
        width: 80%;
        border: 1px solid var(--color-accent);
    }
    
    img {
        height: 120px;
        margin: 7px;
        box-shadow: 7px 7px 7px DimGray;
    }
    
    .photos {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
    }
    Podgląd strony po tym kroku (biuro.php)
  30. Etap 4: Skrypty PHP

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

    Krok 30: Połączenie PDO na początku strony i zamknięcie

    Kryteria: ,

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

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

    ok. 4 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 podroze. Na końcu działania skrypt zamyka połączenie z serwerem.

    Dostęp do bazy stoi na początku pliku biuro.php, przed <!DOCTYPE html>: najpierw dane, potem strona. Klucz przyjmuje bibliotekę MySQLi albo PDO - tu PDO:

    • new PDO('mysql:host=localhost;dbname=podroze;charset=utf8mb4', 'root', '', [...]) - serwer, baza podroze i kodowanie w jednym napisie (DSN), potem użytkownik i puste hasło (R.5.1),
    • ERRMODE_EXCEPTION - błąd bazy rzuca wyjątek; FETCH_ASSOC - wiersze jako tablice z nazwami kolumn,
    • $pdo = null zamyka połączenie. Oba zapytania staną przed tą linią, więc zamknięcie będzie ostatnią operacją na bazie (R.5.2),
    • try/catch (PDOException) - gdy baza nie działa, $error niesie zrozumiały komunikat zamiast treści wyjątku z nazwą serwera i użytkownika.

    Podgląd pokazuje wynik uruchomienia strony - skrypty jeszcze niczego nie wypisują.

    biuro.php PHP zmienione: 12 linii
    <?php
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=podroze;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $pdo = null;
    } catch (PDOException) {
        $error = 'Nie udało się wczytać danych biura. Spróbuj ponownie za chwilę.';
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
        <link rel="stylesheet" href="styl9.css">
    </head>
    <body>
        <header>
            <h1>BIURO PODRÓŻY</h1>
        </header>
        <aside class="promotions">
            <h2>Promocje</h2>
            <table>
                <tr>
                    <td>Warszawa</td>
                    <td>od 600 zł</td>
                </tr>
                <tr>
                    <td>Wenecja</td>
                    <td>od 1200 zł</td>
                </tr>
                <tr>
                    <td>Paryż</td>
                    <td>od 1200 zł</td>
                </tr>
            </table>
        </aside>
        <main class="gallery">
            <h2>W tym roku jedziemy do...</h2>
        </main>
        <aside class="contact">
            <h2>Kontakt</h2>
            <a href="mailto:[email protected]">napisz do nas</a>
            <p>telefon: <a href="tel:+48444555666">444555666</a></p>
        </aside>
        <section class="history">
            <h3>W poprzednich latach byliśmy...</h3>
            <ol>
            </ol>
        </section>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biuro.php)
  31. Krok 31: Skrypt 1: zapytanie 1 i funkcja e()

    Kryteria:

    R.5.3 Skrypt 1 wysyła do bazy danych zapytanie 1 lub skrypt 2 wysyła zapytanie 2

    ok. 3 min
    Polecenie z arkusza

    Skrypt 1: Wysyła do bazy danych zapytanie 1.

    • $pdo->query(...)->fetchAll() wysyła zapytanie 1 i od razu odbiera wszystkie 9 wierszy jako listę tablic z kluczami nazwaPliku i podpis (R.5.3). Zapytanie nie zawiera danych od użytkownika, więc nie trzeba go przygotowywać (prepare),
    • $photos = [] przed try - gdy baza zawiedzie, galeria jest pusta, a strona nadal się wyświetla,
    • funkcja e() (od escape) przepuszcza tekst przez htmlspecialchars z ENT_QUOTES: zamienia <, >, & i oba rodzaje cudzysłowów na encje. Tekst z bazy trafi do atrybutów alt i title - podpis z cudzysłowem (Wieża "Eiffla") bez tej zamiany zamknąłby atrybut w połowie.
    biuro.php PHP zmienione: 9 linii
    <?php
    $photos = [];
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=podroze;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $photos = $pdo->query('SELECT nazwaPliku, podpis FROM zdjecia ORDER BY podpis')->fetchAll();
    
        $pdo = null;
    } catch (PDOException) {
        $error = 'Nie udało się wczytać danych biura. Spróbuj ponownie za chwilę.';
    }
    
    function e(?string $text): string
    {
        return htmlspecialchars($text ?? '', ENT_QUOTES);
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
        <link rel="stylesheet" href="styl9.css">
    </head>
    <body>
        <header>
            <h1>BIURO PODRÓŻY</h1>
        </header>
        <aside class="promotions">
            <h2>Promocje</h2>
            <table>
                <tr>
                    <td>Warszawa</td>
                    <td>od 600 zł</td>
                </tr>
                <tr>
                    <td>Wenecja</td>
                    <td>od 1200 zł</td>
                </tr>
                <tr>
                    <td>Paryż</td>
                    <td>od 1200 zł</td>
                </tr>
            </table>
        </aside>
        <main class="gallery">
            <h2>W tym roku jedziemy do...</h2>
        </main>
        <aside class="contact">
            <h2>Kontakt</h2>
            <a href="mailto:[email protected]">napisz do nas</a>
            <p>telefon: <a href="tel:+48444555666">444555666</a></p>
        </aside>
        <section class="history">
            <h3>W poprzednich latach byliśmy...</h3>
            <ol>
            </ol>
        </section>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

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

  32. Krok 32: Skrypt 1: galeria z bazy

    Kryteria: ,

    R.2.8 W bloku środkowym umieszczono przynajmniej jeden obraz z tekstem alternatywnym (w HTML lub skrypcie)

    R.5.4 Skrypt 1 wyświetla obrazy na podstawie danych zwróconych zapytaniem, w ten sposób, że pole nazwaPliku jest źródłem obrazu, a pole podpis jest tekstem alternatywnym obrazu

    ok. 3 min
    Polecenie z arkusza

    Dane z każdego zwróconego zapytaniem wiersza są wykorzystane do wyświetlenia kolejnych obrazów, w ten sposób, że pole nazwaPliku jest źródłem obrazu, a pole podpis jest tekstem alternatywnym obrazu.

    Pętla foreach ($photos as $photo): ... endforeach; - zapis z dwukropkiem przeznaczony do szablonów: znacznik <img> stoi zwykłym HTML-em, a PHP wstawia tylko wartości przez <?= e(...) ?>. Nazwa pliku idzie do src, podpis do alt (R.2.8, R.5.4). Bez sklejania znaczników w napisach i bez ukośników przed cudzysłowami.

    Podgląd: dziewięć zdjęć od Barcelony do Wenecji, ułożonych przez flexbox w trzy rzędy.

    biuro.php PHP zmienione: 5 linii
    <?php
    $photos = [];
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=podroze;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $photos = $pdo->query('SELECT nazwaPliku, podpis FROM zdjecia ORDER BY podpis')->fetchAll();
    
        $pdo = null;
    } catch (PDOException) {
        $error = 'Nie udało się wczytać danych biura. Spróbuj ponownie za chwilę.';
    }
    
    function e(?string $text): string
    {
        return htmlspecialchars($text ?? '', ENT_QUOTES);
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
        <link rel="stylesheet" href="styl9.css">
    </head>
    <body>
        <header>
            <h1>BIURO PODRÓŻY</h1>
        </header>
        <aside class="promotions">
            <h2>Promocje</h2>
            <table>
                <tr>
                    <td>Warszawa</td>
                    <td>od 600 zł</td>
                </tr>
                <tr>
                    <td>Wenecja</td>
                    <td>od 1200 zł</td>
                </tr>
                <tr>
                    <td>Paryż</td>
                    <td>od 1200 zł</td>
                </tr>
            </table>
        </aside>
        <main class="gallery">
            <h2>W tym roku jedziemy do...</h2>
            <div class="photos">
    <?php foreach ($photos as $photo): ?>
                <img src="<?= e($photo['nazwaPliku']) ?>" alt="<?= e($photo['podpis']) ?>">
    <?php endforeach; ?>
            </div>
        </main>
        <aside class="contact">
            <h2>Kontakt</h2>
            <a href="mailto:[email protected]">napisz do nas</a>
            <p>telefon: <a href="tel:+48444555666">444555666</a></p>
        </aside>
        <section class="history">
            <h3>W poprzednich latach byliśmy...</h3>
            <ol>
            </ol>
        </section>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biuro.php)
  33. Krok 33: Skrypt 1: dymek z podpisem

    Kryteria:

    R.5.5 Skrypt 1 definiuje atrybut title dla każdego obrazu z tekstem z pola podpis zwróconym zapytaniem

    ok. 1 min
    Polecenie z arkusza

    Pole podpis jest tekstem alternatywnym obrazu oraz tekstem pokazującym się w dymku, gdy kursor znajdzie się na grafice, patrz Obraz 2, dymek do grafiki z Londynem.

    Dymek po najechaniu to atrybut title - ten sam podpis drugi raz (R.5.5). alt czyta czytnik ekranu i pokazuje przeglądarka, gdy obrazu brak; title to wskazówka po najechaniu. Najedź w podglądzie na zdjęcie Londynu.

    biuro.php PHP zmienione: 1 linia
    <?php
    $photos = [];
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=podroze;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $photos = $pdo->query('SELECT nazwaPliku, podpis FROM zdjecia ORDER BY podpis')->fetchAll();
    
        $pdo = null;
    } catch (PDOException) {
        $error = 'Nie udało się wczytać danych biura. Spróbuj ponownie za chwilę.';
    }
    
    function e(?string $text): string
    {
        return htmlspecialchars($text ?? '', ENT_QUOTES);
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
        <link rel="stylesheet" href="styl9.css">
    </head>
    <body>
        <header>
            <h1>BIURO PODRÓŻY</h1>
        </header>
        <aside class="promotions">
            <h2>Promocje</h2>
            <table>
                <tr>
                    <td>Warszawa</td>
                    <td>od 600 zł</td>
                </tr>
                <tr>
                    <td>Wenecja</td>
                    <td>od 1200 zł</td>
                </tr>
                <tr>
                    <td>Paryż</td>
                    <td>od 1200 zł</td>
                </tr>
            </table>
        </aside>
        <main class="gallery">
            <h2>W tym roku jedziemy do...</h2>
            <div class="photos">
    <?php foreach ($photos as $photo): ?>
                <img src="<?= e($photo['nazwaPliku']) ?>" alt="<?= e($photo['podpis']) ?>" title="<?= e($photo['podpis']) ?>">
    <?php endforeach; ?>
            </div>
        </main>
        <aside class="contact">
            <h2>Kontakt</h2>
            <a href="mailto:[email protected]">napisz do nas</a>
            <p>telefon: <a href="tel:+48444555666">444555666</a></p>
        </aside>
        <section class="history">
            <h3>W poprzednich latach byliśmy...</h3>
            <ol>
            </ol>
        </section>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biuro.php)
  34. Krok 34: Skrypt 2: dawne wyjazdy w liście

    Kryteria: , ,

    R.2.6 W bloku z danymi umieszczono jedną listę numerowaną, zastosowano znaczniki <ol>, <li> (w skrypcie lub HTML)

    R.5.6 Skrypt 2 wyświetla każdy zwrócony wiersz w elemencie listy w formacie: „Dnia <data> pojechaliśmy do <cel>”, gdzie < > oznacza pole zwrócone zapytaniem

    R.5.7 Zastosowano znaczące nazewnictwo dla wszystkich zmiennych lub funkcji w języku polskim lub angielskim. Nazwy odzwierciedlają cel zastosowania

    ok. 4 min
    Polecenie z arkusza

    Skrypt 2: Wysyła do bazy danych zapytanie 2. Każdy zwrócony zapytaniem wiersz jest wyświetlany w elemencie listy, według wzoru: „Dnia <data> pojechaliśmy do <cel>”, gdzie w znakach < > zapisano pola zwracane zapytaniem.

    • drugie zapytanie na tym samym połączeniu, przed jego zamknięciem; $pastTrips startuje pusta przed try (R.5.3),
    • pętla wypisuje jeden <li> na wiersz. Kolumny są po nazwach ($trip['dataWyjazdu'], $trip['cel']), więc kolejność pól w zdaniu nie zależy od kolejności kolumn w zapytaniu (R.2.6, R.5.6),
    • data stoi w znaczniku <time datetime="..."> - przeglądarki i wyszukiwarki wiedzą, że to data. Na ekranie zostaje w postaci z bazy, jak wymaga wzór arkusza.

    Podgląd: trzy elementy listy numerowane I, II, III, jak na obrazie 2. Nazwy mówią, co przechowują: $photos, $pastTrips, $trip, e() (R.5.7).

    biuro.php PHP zmienione: 7 linii
    <?php
    $photos = [];
    $pastTrips = [];
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=podroze;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $photos = $pdo->query('SELECT nazwaPliku, podpis FROM zdjecia ORDER BY podpis')->fetchAll();
    
        $pastTrips = $pdo->query('SELECT cel, dataWyjazdu FROM wycieczki
            WHERE dostepna = FALSE ORDER BY dataWyjazdu, cel')->fetchAll();
    
        $pdo = null;
    } catch (PDOException) {
        $error = 'Nie udało się wczytać danych biura. Spróbuj ponownie za chwilę.';
    }
    
    function e(?string $text): string
    {
        return htmlspecialchars($text ?? '', ENT_QUOTES);
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
        <link rel="stylesheet" href="styl9.css">
    </head>
    <body>
        <header>
            <h1>BIURO PODRÓŻY</h1>
        </header>
        <aside class="promotions">
            <h2>Promocje</h2>
            <table>
                <tr>
                    <td>Warszawa</td>
                    <td>od 600 zł</td>
                </tr>
                <tr>
                    <td>Wenecja</td>
                    <td>od 1200 zł</td>
                </tr>
                <tr>
                    <td>Paryż</td>
                    <td>od 1200 zł</td>
                </tr>
            </table>
        </aside>
        <main class="gallery">
            <h2>W tym roku jedziemy do...</h2>
            <div class="photos">
    <?php foreach ($photos as $photo): ?>
                <img src="<?= e($photo['nazwaPliku']) ?>" alt="<?= e($photo['podpis']) ?>" title="<?= e($photo['podpis']) ?>">
    <?php endforeach; ?>
            </div>
        </main>
        <aside class="contact">
            <h2>Kontakt</h2>
            <a href="mailto:[email protected]">napisz do nas</a>
            <p>telefon: <a href="tel:+48444555666">444555666</a></p>
        </aside>
        <section class="history">
            <h3>W poprzednich latach byliśmy...</h3>
            <ol>
    <?php foreach ($pastTrips as $trip): ?>
                <li>Dnia <time datetime="<?= e($trip['dataWyjazdu']) ?>"><?= e($trip['dataWyjazdu']) ?></time> pojechaliśmy do <?= e($trip['cel']) ?></li>
    <?php endforeach; ?>
            </ol>
        </section>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (biuro.php)
  35. Krok 35: Komunikat, gdy baza nie działa

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloku środkowego: Efekt działania skryptu 1.

    Gdy połączenie albo zapytanie się nie uda, catch ustawia $error, a blok środkowy wyświetla komunikat pod nagłówkiem zamiast pustego miejsca po galerii. isset($error) sprawdza, czy zmienna w ogóle powstała.

    Sprawdzone z błędną nazwą bazy: strona wyświetla wszystkie bloki, komunikat i pustą listę wyjazdów, bez ostrzeżeń PHP. Klucz tego nie ocenia.

    biuro.php PHP zmienione: 3 linie
    <?php
    $photos = [];
    $pastTrips = [];
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=podroze;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $photos = $pdo->query('SELECT nazwaPliku, podpis FROM zdjecia ORDER BY podpis')->fetchAll();
    
        $pastTrips = $pdo->query('SELECT cel, dataWyjazdu FROM wycieczki
            WHERE dostepna = FALSE ORDER BY dataWyjazdu, cel')->fetchAll();
    
        $pdo = null;
    } catch (PDOException) {
        $error = 'Nie udało się wczytać danych biura. Spróbuj ponownie za chwilę.';
    }
    
    function e(?string $text): string
    {
        return htmlspecialchars($text ?? '', ENT_QUOTES);
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Poznaj Europę</title>
        <link rel="stylesheet" href="styl9.css">
    </head>
    <body>
        <header>
            <h1>BIURO PODRÓŻY</h1>
        </header>
        <aside class="promotions">
            <h2>Promocje</h2>
            <table>
                <tr>
                    <td>Warszawa</td>
                    <td>od 600 zł</td>
                </tr>
                <tr>
                    <td>Wenecja</td>
                    <td>od 1200 zł</td>
                </tr>
                <tr>
                    <td>Paryż</td>
                    <td>od 1200 zł</td>
                </tr>
            </table>
        </aside>
        <main class="gallery">
            <h2>W tym roku jedziemy do...</h2>
    <?php if (isset($error)): ?>
            <p class="error"><?= e($error) ?></p>
    <?php endif; ?>
            <div class="photos">
    <?php foreach ($photos as $photo): ?>
                <img src="<?= e($photo['nazwaPliku']) ?>" alt="<?= e($photo['podpis']) ?>" title="<?= e($photo['podpis']) ?>">
    <?php endforeach; ?>
            </div>
        </main>
        <aside class="contact">
            <h2>Kontakt</h2>
            <a href="mailto:[email protected]">napisz do nas</a>
            <p>telefon: <a href="tel:+48444555666">444555666</a></p>
        </aside>
        <section class="history">
            <h3>W poprzednich latach byliśmy...</h3>
            <ol>
    <?php foreach ($pastTrips as $trip): ?>
                <li>Dnia <time datetime="<?= e($trip['dataWyjazdu']) ?>"><?= e($trip['dataWyjazdu']) ?></time> pojechaliśmy do <?= e($trip['cel']) ?></li>
    <?php endforeach; ?>
            </ol>
        </section>
        <footer>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    styl9.css CSS zmienione: 5 linii
    :root {
        --color-dark: #BA6B6C;
        --color-side: #EF9A9A;
        --color-light: MistyRose;
        --color-accent: Maroon;
    }
    
    * {
        font-family: Georgia, serif;
        text-align: center;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        padding: 7px;
    }
    
    .promotions,
    .contact {
        background-color: var(--color-side);
        height: 500px;
    }
    
    .gallery {
        background-color: var(--color-light);
        height: 500px;
    }
    
    body {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        grid-template-areas:
            "header     header  header"
            "promotions gallery contact"
            "history    history history"
            "footer     footer  footer";
    }
    
    header      { grid-area: header; }
    .promotions { grid-area: promotions; }
    .gallery    { grid-area: gallery; }
    .contact    { grid-area: contact; }
    .history    { grid-area: history; }
    footer      { grid-area: footer; }
    
    .history {
        background-color: var(--color-light);
        padding: 50px;
    }
    
    ol {
        list-style-type: upper-roman;
    }
    
    li {
        text-align: left;
    }
    
    h2::first-letter {
        font-size: 170%;
        color: var(--color-accent);
    }
    
    table {
        margin: auto;
        width: 80%;
        border: 1px solid var(--color-accent);
    }
    
    img {
        height: 120px;
        margin: 7px;
        box-shadow: 7px 7px 7px DimGray;
    }
    
    .photos {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
    }
    
    .error {
        color: var(--color-accent);
        font-weight: bold;
    }
    Podgląd strony po tym kroku (biuro.php)
  36. Etap 5: Porównanie z wersją podstawową

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

    Krok 36: Co jest inaczej i dlaczego

    ok. 3 min
    Polecenie z arkusza

    Ocenie będzie podlegać 5 rezultatów: operacje na bazie danych, zawartość witryny internetowej, działanie witryny internetowej, styl CSS witryny internetowej, skrypt połączenia z bazą.

    Obie wersje dają te same punkty. Różnice:

    wersja podstawowata wersja
    SQLzapytania w jednej linii, dostepna = 0klauzule w liniach, = FALSE, aliasy tabel, ORDER BY w zapytaniu 2
    układfloat: left + clear: bothsiatka 20% / 60% / 20% na <body>
    bloki<section> z identyfikatorami left, middle...aside, main, section z klasami od treści
    kolorywpisane w każdej regulezmienne w :root
    galeriazdjęcia w linii tekstuflexbox .photos
    bibliotekamysqli_* w dwóch blokach PHP w treściPDO na początku pliku, w HTML-u tylko wyświetlanie
    kolumny wierszanumery ($row[1] przed $row[0])nazwy ($trip['dataWyjazdu'])
    atrybuty alt/titlepodpis wprost z bazyprzez e()
    błąd bazyostrzeżenia PHPkomunikat dla użytkownika

    Sprawdzone: podgląd każdego kroku to prawdziwe uruchomienie w PHP 8.2 na MariaDB, układ zmierzony w Chrome (bloki 20/60/20% w jednym rzędzie po 500 px, 9 zdjęć po 120 px w trzech rzędach mieszczących się w galerii, lista z cyframi rzymskimi), awaria bazy daje komunikat bez ostrzeżeń.

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

  37. Krok 37: Którą wersję wybrać na egzaminie

    ok. 2 min
    Polecenie z arkusza

    Czas przeznaczony na wykonanie zadania wynosi 150 minut.

    • Wersja podstawowa, gdy liczy się czas: funkcje mysqli_* są w tabeli 1 arkusza, a float wystarczy do trzech bloków obok siebie.
    • Ta wersja, gdy PDO i siatkę CSS pisze się z pamięci. Szablon z foreach: ... endforeach; i <?= e(...) ?> jest odporny na najczęstszy błąd egzaminacyjny - pomylone cudzysłowy w echo budującym znacznik <img>.

    Mieszanie też daje pełne punkty: siatka i zmienne z tej wersji, mysqli z podstawowej.

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

  38. Etap 6: Oddanie pracy

    Krok 38 · po tym etapie masz 34 z 34 kryteriów (pkt)

    Krok 38: 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 nazwa przeglądarki, w której strona była sprawdzana.

    W folderze: zdjęcia 1.jpg - 9.jpg, biuro.php, import.png, kw1.jpg - kw4.jpg, kwerendy.txt, przeglądarka.txt, styl9.css. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem zdającego.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

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

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.