Przejdź do głównej treści
INF.03-02-23.01-SGStyczeń 2023 · 33 kroki · ok. 68 min · 33 kryteria z klucza

Rozwiązanie krok po kroku: Witryna pensjonatu z cennikiem (Nowoczesny kod (grid, PDO))

To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza wynajem z pięcioma zapytaniami, trzy zdjęcia 300 × 300 px w odcieniach szarości i strony index.html, cennik.php i kalkulator.html z arkuszem stylów styl2.css - i tak samo spełnia każde kryterium klucza. Inna jest droga:

  • siatka CSS zamiast float: trzy bloki stoją w znaczniku <main>, a szerokość 30% opisuje jedna reguła grid-template-columns; stopka nie potrzebuje clear,
  • zmienne CSS dla kolorów z arkusza i aria-current przy odnośniku do bieżącej strony,
  • zapytania pisane czytelnie: klauzule w osobnych liniach, lista pól zamiast *, alias przy sumie,
  • PHP na PDO: cennik strona pobiera na górze pliku cennik.php, przed HTML-em, w bloku try, a w tabeli zostaje tylko pętla foreach i bezpieczne wypisywanie (htmlspecialchars w funkcji e()),
  • komunikaty zamiast pustej tabeli, gdy cennik jest pusty albo bazy nie da się odczytać.

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

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

  1. Etap 1: Baza danych

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

    Krok 1: Baza danych wynajem

    ok. 2 min
    Polecenie z arkusza

    Utwórz bazę danych o nazwie wynajem

    Rozpakuj zad2.zip z pulpitu (hasło MN52dc%% - z dwoma znakami procentu na końcu) do folderu z numerem zdającego: wynajem.sql i trzy zdjęcia BMP. W phpMyAdmin Nowa → wynajem albo zapytaniem:

    CREATE DATABASE wynajem CHARACTER SET utf8mb4 COLLATE utf8mb4_polish_ci;
    

    Arkusz nie podaje porównywania, więc wybór należy do Ciebie. Tabele z wynajem.sql mają zestaw utf8mb4 zapisany we własnej definicji, więc ustawienie bazy ich nie zmienia.

    Typowe błędy

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

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

    ok. 2 min
    Polecenie z arkusza

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

    Zaznaczona baza wynajem, Import → wynajem.sql → Wykonaj. Dwie tabele z obrazu 1: pokoje (3 rodzaje pokoi z ceną) i rezerwacje (10 rezerwacji: pokój id_pok, liczba dni liczba_dn, sezon „lato” albo „zima”).

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

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

    Cały ekran z paskiem zadań, w PNG, pod nazwą import. Zrzuty zapytań kw1 - kw5 będą już w JPEG.

    Typowe błędy

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

  4. Krok 4: Zapytanie 1: wszystkie pokoje

    Kryteria: ,

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

    R.1.3 Utworzono zapytanie 1 wybierające wszystkie wiersze z tabeli pokoje . W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT * FROM pokoje; oraz wynik działania udokumentowano zrzutem, na którym widoczne są wszystkie dane z tabeli: trzy rekordy z polami id, nazwa, cena

    ok. 1 min
    Polecenie z arkusza

    Zapytanie 1: wybierające wszystkie wiersze z tabeli pokoje

    Bez warunku WHERE, więc wszystkie wiersze. Zamiast * stoi lista pól id, nazwa, cena - zapytanie mówi wprost, jakich kolumn potrzebuje, i nie zmieni wyniku, gdy ktoś dopisze do tabeli nowe pole. To samo zapytanie wyśle skrypt cennika. Wynik: trzy pokoje z polami id, nazwa, cena. Zapytanie do kwerendy.txt, zrzut kw1.jpg.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT id, nazwa, cena
    FROM pokoje;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: rezerwacje dłuższe niż tydzień

    Kryteria:

    R.1.4 Utworzono zapytanie 2 wybierające z tabeli rezerwacje jedynie id pokoju oraz sezon dla rezerwacji o liczbie dni przekraczającej tydzień. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id_pok, sezon FROM rezerwacje WHERE liczba_dn > 7; oraz wynik działania udokumentowano zrzutem, na którym widoczne są dokładnie 3 rekordy z danymi: 1, lato; 3, zima; 1, zima

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 2: wybierające z tabeli rezerwacje jedynie id pokoju oraz sezon dla rezerwacji o liczbie dni przekraczającej tydzień

    id_pok to numer pokoju (nie rezerwacji), a „przekraczającej tydzień” to więcej niż 7 dni: liczba_dn > 7. Wynik: 1, lato; 3, zima; 1, zima - jak w kluczu. Zrzut: kw2.jpg.

    kwerendy.txt Tekst zmienione: 5 linii
    -- Zapytanie 1
    SELECT id, nazwa, cena
    FROM pokoje;
    
    -- Zapytanie 2
    SELECT id_pok, sezon
    FROM rezerwacje
    WHERE liczba_dn > 7;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: suma dni rezerwacji zimą

    Kryteria:

    R.1.5 Utworzono zapytanie 3 liczące sumę dni rezerwacji zimą. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT SUM(liczba_dn) FROM rezerwacje WHERE sezon = "zima"; oraz wynik działania udokumentowano zrzutem, na którym widoczna jest wartość 25 lub 27

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 3: liczące sumę dni rezerwacji zimą

    SUM(liczba_dn) dodaje dni ze wszystkich wierszy spełniających warunek, a alias dni_zima daje kolumnie wyniku czytelną nazwę zamiast SUM(liczba_dn). Wynik: 25 (2 + 6 + 9 + 8). Klucz uznaje też 27 - tyle wychodzi po zapytaniu 4, które dwudniową rezerwację zimową wydłuża do 4 dni. Zrzut: kw3.jpg.

    kwerendy.txt Tekst zmienione: 5 linii
    -- Zapytanie 1
    SELECT id, nazwa, cena
    FROM pokoje;
    
    -- Zapytanie 2
    SELECT id_pok, sezon
    FROM rezerwacje
    WHERE liczba_dn > 7;
    
    -- Zapytanie 3
    SELECT SUM(liczba_dn) AS dni_zima
    FROM rezerwacje
    WHERE sezon = 'zima';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: minimum 4 dni rezerwacji

    Kryteria:

    R.1.6 Utworzono zapytanie 4 aktualizujące liczbę dni rezerwacji, dla rekordów, w których liczba dni jest mniejsza od 4 liczba ta jest ustawiana na 4. W pliku z kwerendami lub na zrzucie istnieje zapis np.: UPDATE rezerwacje SET liczba_dn = 4 WHERE liczba_dn < 4; oraz wynik działania udokumentowano zrzutem, na którym widoczny jest komunikat o poprawnej aktualizacji lub tabela ze zaktualizowanymi danymi

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 4: aktualizujące liczbę dni rezerwacji. Minimalna liczba dni rezerwacji to 4, dla rekordów, w których liczba dni jest mniejsza od 4 liczba ta jest zmieniana na 4

    UPDATE zmienia istniejące wiersze, SET podaje nową wartość, a WHERE liczba_dn < 4 ogranicza zmianę do krótszych rezerwacji. Komunikat: 3 wiersze zmienione (rezerwacje na 2, 3 i 3 dni). Zrzut kw4.jpg pokazuje komunikat i tabelę po zmianie.

    Typowe błędy

    UPDATE bez WHERE zmienia wszystkie wiersze - cofnięcie wymaga ponownego importu bazy.

    kwerendy.txt Tekst zmienione: 5 linii
    -- Zapytanie 1
    SELECT id, nazwa, cena
    FROM pokoje;
    
    -- Zapytanie 2
    SELECT id_pok, sezon
    FROM rezerwacje
    WHERE liczba_dn > 7;
    
    -- Zapytanie 3
    SELECT SUM(liczba_dn) AS dni_zima
    FROM rezerwacje
    WHERE sezon = 'zima';
    
    -- Zapytanie 4
    UPDATE rezerwacje
    SET liczba_dn = 4
    WHERE liczba_dn < 4;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Krok 8: Zapytanie 5: użytkownik najemca z hasłem

    Kryteria:

    R.1.7 Utworzono zapytanie 5 tworzące użytkownika najemca z hasłem n@JEM1@! W pliku z kwerendami lub na zrzucie istnieje zapis z jawnie zapisanym hasłem np.: CREATE USER najemca IDENTIFIED BY "n@JEM1@!"; oraz wynik działania udokumentowano zrzutem, na którym widoczny jest komunikat o poprawnym dodaniu użytkownika lub dodany użytkownik widoczny jest na liście

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 5: tworzące użytkownika najemca z hasłem n@JEM1@!

    'najemca'@'localhost' to konto, które może logować się tylko z tego samego komputera - bezpieczniejsze niż konto bez hosta ('najemca'@'%', dowolny komputer), które klucz też uznaje. IDENTIFIED BY z hasłem zapisanym jawnie, jak wymaga klucz. Sprawdzone logowanie nowym kontem: działa, a konto nie ma jeszcze żadnych uprawnień - arkusz o nie nie prosi. Zrzut kw5.jpg: komunikat i konto na liście użytkowników.

    Typowe błędy

    Hasło musi być dokładnie n@JEM1@! - wielkość liter ma znaczenie, a znak ! na końcu łatwo zgubić.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT id, nazwa, cena
    FROM pokoje;
    
    -- Zapytanie 2
    SELECT id_pok, sezon
    FROM rezerwacje
    WHERE liczba_dn > 7;
    
    -- Zapytanie 3
    SELECT SUM(liczba_dn) AS dni_zima
    FROM rezerwacje
    WHERE sezon = 'zima';
    
    -- Zapytanie 4
    UPDATE rezerwacje
    SET liczba_dn = 4
    WHERE liczba_dn < 4;
    
    -- Zapytanie 5
    CREATE USER 'najemca'@'localhost' IDENTIFIED BY 'n@JEM1@!';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Etap 2: Grafika i strony HTML

    Kroki 9-20 · po tym etapie masz 17 z 33 kryteriów (pkt)

    Krok 9: Zdjęcia 1-3: 300 × 300 px, odcienie szarości, JPEG

    Kryteria:

    R.2.1 Przynajmniej jeden obraz 1 , 2 lub 3 zapisano w formacie JPEG w odcieniach szarości i dokładnych wymiarach 300 px na 300 px

    ok. 5 min
    Polecenie z arkusza

    Obrazy 1.bmp, 2.bmp, 3.bmp należy przeskalować bez zachowania proporcji do wymiarów 300 px na 300 px oraz zapisać w odcieniach szarości i w formacie JPEG

    Grafika jest taka sama jak w wersji podstawowej. W GIMP-ie dla każdego pliku: Obraz → Skaluj obraz z rozłączonym łańcuchem proporcji, 300 × 300; Obraz → Tryb → Odcienie szarości; Plik → Wyeksportuj jako 1.jpg (2.jpg, 3.jpg) - format zmienia rozszerzenie przy eksporcie.

    Typowe błędy

    Zmiana samego rozszerzenia w Eksploratorze (1.bmp na 1.jpg) nie zmienia formatu pliku - klucz wymaga JPEG.

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

    ok. 2 min
    Polecenie z arkusza

    Cechy wspólne dla stron index.html i cennik.php: Zapisane w języku HTML 5. Jawnie zastosowany właściwy standard kodowania polskich znaków. Zadeklarowany język witryny: polski.

    Najpierw cała strona index.html; cennik.php będzie jej kopią z innym blokiem środkowym. <!DOCTYPE html>, <html lang="pl"> i <meta charset="UTF-8"> jako pierwszy element <head>.

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

    Kryteria:

    R.2.3 Nadano tytuł stronie: "Wynajem pokoi"

    ok. 1 min
    Polecenie z arkusza

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

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

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

    Kryteria:

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

    ok. 1 min
    Polecenie z arkusza

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

    Nazwa z cyfrą 2: styl2.css. Całe formatowanie pochodzi z tego pliku (R.3.5).

    Typowe błędy

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

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Wynajem pokoi</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  13. Krok 13: Bloki: baner, trzy bloki w main, stopka

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: baner, poniżej obok siebie blok lewy, środkowy i prawy, na dole 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

    Baner to <header>, stopka <footer>, a trzy bloki - trzy <section> we wspólnym <main>: to główna treść strony i zarazem pojemnik, który w CSS ustawi bloki w rząd (R.2.4). Bloki wyglądają jednakowo, więc nie potrzebują identyfikatorów - wystarczy selektor section.

    index.html HTML zmienione: 12 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Wynajem pokoi</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
        </header>
        <main>
            <section>
            </section>
            <section>
            </section>
            <section>
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  14. Krok 14: Baner: nagłówek pierwszego stopnia

    ok. 1 min
    Polecenie z arkusza

    Zawartość banera: nagłówek pierwszego stopnia o treści „Pensjonat pod dobrym humorem”

    <h1> w <header>.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Wynajem pokoi</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Pensjonat pod dobrym humorem</h1>
        </header>
        <main>
            <section>
            </section>
            <section>
            </section>
            <section>
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  15. Krok 15: Blok lewy: odnośnik GŁÓWNA i zdjęcie 1.jpg

    Kryteria:

    R.3.2 Po wybraniu odnośnika GŁÓWNA otwiera się strona index.html

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloku lewego: odnośnik „GŁÓWNA” do pliku index.html, obraz 1.jpg z tekstem alternatywnym „pokoje”

    Odnośnik do strony głównej i zdjęcie z tekstem alternatywnym z arkusza (R.3.2). aria-current="page" oznacza odnośnik do strony, która jest właśnie otwarta - czytnik ekranu odczyta „bieżąca strona”.

    index.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Wynajem pokoi</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Pensjonat pod dobrym humorem</h1>
        </header>
        <main>
            <section>
                <a href="index.html" aria-current="page">GŁÓWNA</a>
                <img src="1.jpg" alt="pokoje">
            </section>
            <section>
            </section>
            <section>
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  16. Krok 16: Blok prawy: odnośnik KALKULATOR i zdjęcie 3.jpg

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku prawego: odnośnik „KALKULATOR” do pliku kalkulator.html, obraz 3.jpg z tekstem alternatywnym „pokoje”

    To samo co w bloku lewym. Arkusz opisuje blok prawy przed środkowym, bo tylko środkowy różni się między stronami.

    index.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Wynajem pokoi</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Pensjonat pod dobrym humorem</h1>
        </header>
        <main>
            <section>
                <a href="index.html" aria-current="page">GŁÓWNA</a>
                <img src="1.jpg" alt="pokoje">
            </section>
            <section>
            </section>
            <section>
                <a href="kalkulator.html">KALKULATOR</a>
                <img src="3.jpg" alt="pokoje">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  17. Krok 17: Stopka

    Kryteria:

    R.2.5 W banerze zapisano nagłówek h1: "Pensjonat pod dobrym humorem" oraz paragraf w stopce

    ok. 1 min
    Polecenie z arkusza

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

    Akapit w <footer>. Na egzaminie wpisujesz swój numer zdającego (PESEL), tu stoi autor rozwiązania. Z nagłówkiem w banerze to R.2.5.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Wynajem pokoi</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Pensjonat pod dobrym humorem</h1>
        </header>
        <main>
            <section>
                <a href="index.html" aria-current="page">GŁÓWNA</a>
                <img src="1.jpg" alt="pokoje">
            </section>
            <section>
            </section>
            <section>
                <a href="kalkulator.html">KALKULATOR</a>
                <img src="3.jpg" alt="pokoje">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  18. Krok 18: index.html, blok środkowy: odnośnik CENNIK i zdjęcie 2.jpg

    Kryteria: ,

    R.2.7 Na stronie głównej w blokach lewym, środkowym i prawym umieszczono trzy grafiki o nazwach 1 , 2 , 3 (w formacie BMP lub JPEG) i tekście alternatywnym "pokoje"

    R.3.3 Po wybraniu odnośnika CENNIK otwiera się strona cennik.php

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku środkowego dla strony index.html: odnośnik „CENNIK” do pliku cennik.php, obraz 2.jpg z tekstem alternatywnym „pokoje”

    Trzecie zdjęcie - na stronie głównej są już wszystkie trzy obrazy z tekstem „pokoje” (R.2.7, R.3.3).

    index.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Wynajem pokoi</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Pensjonat pod dobrym humorem</h1>
        </header>
        <main>
            <section>
                <a href="index.html" aria-current="page">GŁÓWNA</a>
                <img src="1.jpg" alt="pokoje">
            </section>
            <section>
                <a href="cennik.php">CENNIK</a>
                <img src="2.jpg" alt="pokoje">
            </section>
            <section>
                <a href="kalkulator.html">KALKULATOR</a>
                <img src="3.jpg" alt="pokoje">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  19. Krok 19: cennik.php: kopia strony z tabelą zamiast zdjęcia

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

    Strony index.html i cennik.php różnią się jedynie blokiem środkowym. Zawartość bloku środkowego dla strony cennik.php: odnośnik „CENNIK” do pliku cennik.php, tabela o trzech kolumnach wypełniana skryptem

    Kopia index.html zapisana jako cennik.php: zamiast zdjęcia 2.jpg jest pusta tabela - wiersze wypisze skrypt, a aria-current przechodzi na odnośnik CENNIK. Rozszerzenie .php - strona działa tylko otwarta przez http://localhost/.... Witryna jest w obu plikach, z HTML5, kodowaniem i językiem (R.2.2).

    cennik.php PHP nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Wynajem pokoi</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Pensjonat pod dobrym humorem</h1>
        </header>
        <main>
            <section>
                <a href="index.html">GŁÓWNA</a>
                <img src="1.jpg" alt="pokoje">
            </section>
            <section>
                <a href="cennik.php" aria-current="page">CENNIK</a>
                <table>
                </table>
            </section>
            <section>
                <a href="kalkulator.html">KALKULATOR</a>
                <img src="3.jpg" alt="pokoje">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (cennik.php)
  20. Krok 20: kalkulator.html: strona w trakcie budowy

    Kryteria:

    R.3.4 Po wybraniu odnośnika KALKULATOR otwiera się strona kalkulator.html

    ok. 1 min
    Polecenie z arkusza

    Na stronie kalkulator.html należy jedynie zapisać „strona w trakcie budowy”

    Najkrótsza poprawna strona HTML5 z jednym akapitem - arkusz każe zapisać na niej tylko ten napis. Odnośnik KALKULATOR już działa (R.3.4).

    kalkulator.html HTML nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Wynajem pokoi</title>
    </head>
    <body>
        <p>strona w trakcie budowy</p>
    </body>
    </html>
    Podgląd strony po tym kroku (kalkulator.html)
  21. Etap 3: Styl CSS

    Kroki 21-27 · po tym etapie masz 28 z 33 kryteriów (pkt)

    Krok 21: Plik styl2.css: zmienne, krój i wyśrodkowanie

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

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

    Dwa kolory z arkusza w zmiennych (--header, --block), wywoływane przez var(...). Selektor * z Garamondem i krojem zapasowym serif (R.4.1).

    styl2.css CSS nowy plik
    :root {
        --header: #AF8EB5;
        --block: #E1BEE7;
    }
    
    * {
        font-family: Garamond, serif;
        text-align: center;
    }
    Podgląd strony po tym kroku (index.html)
  22. Krok 22: Ciało strony: kolor tła

    ok. 1 min
    Polecenie z arkusza

    Dla selektora ciała strony: kolor tła Lavender

    Selektor body, kolor z listy nazw CSS.

    styl2.css CSS zmienione: 4 linie
    :root {
        --header: #AF8EB5;
        --block: #E1BEE7;
    }
    
    * {
        font-family: Garamond, serif;
        text-align: center;
    }
    
    body {
        background-color: Lavender;
    }
    Podgląd strony po tym kroku (index.html)
  23. Krok 23: Baner i stopka

    ok. 1 min
    Polecenie z arkusza

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

    Jedna reguła dla dwóch selektorów, kolor ze zmiennej.

    styl2.css CSS zmienione: 7 linii
    :root {
        --header: #AF8EB5;
        --block: #E1BEE7;
    }
    
    * {
        font-family: Garamond, serif;
        text-align: center;
    }
    
    body {
        background-color: Lavender;
    }
    
    header,
    footer {
        background-color: var(--header);
        color: white;
        padding: 10px;
    }
    Podgląd strony po tym kroku (index.html)
  24. Krok 24: Układ: trzy kolumny siatki po 30%

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: baner, poniżej obok siebie blok lewy, środkowy i prawy, na dole 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

    display: grid na <main> i grid-template-columns: repeat(3, 30%) - trzy kolumny po 30% szerokości strony; repeat zapisuje trzy jednakowe kolumny bez powtarzania wartości. Klucz przy R.4.4 wprost przyjmuje szerokość podaną w ten sposób.

    Pozostałe 10% szerokości zostaje wolne po prawej, jak na obrazie 2. Baner i stopka są poza siatką, więc stoją nad i pod nią same z siebie - bez float i bez clear (R.3.1).

    styl2.css CSS zmienione: 5 linii
    :root {
        --header: #AF8EB5;
        --block: #E1BEE7;
    }
    
    * {
        font-family: Garamond, serif;
        text-align: center;
    }
    
    body {
        background-color: Lavender;
    }
    
    header,
    footer {
        background-color: var(--header);
        color: white;
        padding: 10px;
    }
    
    main {
        display: grid;
        grid-template-columns: repeat(3, 30%);
    }
    Podgląd strony po tym kroku (index.html)
  25. Krok 25: Bloki lewy, środkowy i prawy

    Kryteria: , ,

    R.4.2 Ustawiono kolor tła Lavender dla selektora body, #AF8EB5 dla banera i stopki, kolor tła #E1BEE7 dla bloków lewego, środkowego i prawego

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

    R.4.9 Ustawiono cień bloku lewego, środkowego i prawego box-shadow: 10px 10px 10px DimGray (poprawnie również 10px 10px 10px 0 DimGray)

    ok. 3 min
    Polecenie z arkusza

    Wspólne dla bloków lewego, środkowego i prawego: kolor tła #E1BEE7, szerokość 30%, wysokość 500 px, margines wewnętrzny górny 40 px, marginesy zewnętrzne 15 px, cień bloku o przesunięciu 10 px w obu osiach, rozmyciu 10 px i kolorze DimGray

    Szerokość już jest - w kolumnach siatki. Tu kolor, wysokość, padding-top, margines i cień (składnia z arkusza: przesunięcie poziome, pionowe, rozmycie, kolor).

    Margines w siatce działa wewnątrz kolumny: blok odsuwa się o 15 px od jej krawędzi, więc jest o 30 px węższy niż kolumna - między blokami widać lawendowe tło, jak na obrazie 2. W wersji z float margines dochodzi do szerokości 30%, tu jest od niej odejmowany; dzięki temu trzy bloki zawsze mieszczą się w jednym rzędzie, także w wąskim oknie.

    styl2.css CSS zmienione: 8 linii
    :root {
        --header: #AF8EB5;
        --block: #E1BEE7;
    }
    
    * {
        font-family: Garamond, serif;
        text-align: center;
    }
    
    body {
        background-color: Lavender;
    }
    
    header,
    footer {
        background-color: var(--header);
        color: white;
        padding: 10px;
    }
    
    main {
        display: grid;
        grid-template-columns: repeat(3, 30%);
    }
    
    section {
        background-color: var(--block);
        height: 500px;
        padding-top: 40px;
        margin: 15px;
        box-shadow: 10px 10px 10px DimGray;
    }
    Podgląd strony po tym kroku (index.html)
  26. Krok 26: Odnośniki i ich wygląd pod kursorem

    Kryteria: , , ,

    R.4.3 Ustawiono biały kolor czcionki dla banera i stopki oraz Indigo dla selektora a

    R.4.6 Ustawiono marginesy wewnętrzne (padding) 10px dla banera, stopki i odnośnika, oraz padding-top: 40px i marginesy zewnętrzne (margin) 15px dla dla bloków lewego, środkowego i prawego

    R.4.8 Ustawiono cechy dla odnośnika: rozmiar czcionki 150%, czcionka pogrubiona

    R.4.10 Gdy kursor znajdzie się na odnośniku jego kolor tła zmienia się na Indigo a kolor czcionki na biały np. a:hover

    ok. 2 min
    Polecenie z arkusza

    Dla selektora odnośnika: kolor czcionki Indigo, rozmiar czcionki 150%, marginesy wewnętrzne 10 px, czcionka pogrubiona. Gdy kursor znajdzie się na odnośniku jego kolor tła zmienia się na Indigo, a kolor czcionki na biały

    Selektor znacznika a, jak każe uwaga arkusza. padding widać dopiero pod kursorem: a:hover daje odnośnikowi tło, a margines wewnętrzny robi z niego prostokąt wokół napisu, jak przy CENNIK na obrazie 2 (R.4.3, R.4.6, R.4.8, R.4.10).

    styl2.css CSS zmienione: 12 linii
    :root {
        --header: #AF8EB5;
        --block: #E1BEE7;
    }
    
    * {
        font-family: Garamond, serif;
        text-align: center;
    }
    
    body {
        background-color: Lavender;
    }
    
    header,
    footer {
        background-color: var(--header);
        color: white;
        padding: 10px;
    }
    
    main {
        display: grid;
        grid-template-columns: repeat(3, 30%);
    }
    
    section {
        background-color: var(--block);
        height: 500px;
        padding-top: 40px;
        margin: 15px;
        box-shadow: 10px 10px 10px DimGray;
    }
    
    a {
        color: Indigo;
        font-size: 150%;
        padding: 10px;
        font-weight: bold;
    }
    
    a:hover {
        background-color: Indigo;
        color: white;
    }
    Podgląd strony po tym kroku (index.html)
  27. Krok 27: Obraz i tabela: obramowanie, szerokość, marginesy

    Kryteria: ,

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

    R.4.7 Ustawiono obramowanie dla obrazu i tabeli: linia ciągła 1px oraz marginesy zewnętrzne (margin) górny i dolny 40 px, lewy i prawy auto

    ok. 2 min
    Polecenie z arkusza

    Wspólne dla selektora obrazu i tabeli: obramowanie linią ciągłą o szerokości 1 px, szerokość 80%, marginesy zewnętrzne górny i dolny 40 px, lewy i prawy automatycznie wyliczany przez przeglądarkę

    margin: 40px auto - górny i dolny 40 px, lewy i prawy wyliczane przez przeglądarkę. Bez koloru obramowanie bierze kolor tekstu. Szerokość 80% liczy się od bloku, w którym stoi obraz albo tabela (R.4.4, R.4.7).

    styl2.css CSS zmienione: 7 linii
    :root {
        --header: #AF8EB5;
        --block: #E1BEE7;
    }
    
    * {
        font-family: Garamond, serif;
        text-align: center;
    }
    
    body {
        background-color: Lavender;
    }
    
    header,
    footer {
        background-color: var(--header);
        color: white;
        padding: 10px;
    }
    
    main {
        display: grid;
        grid-template-columns: repeat(3, 30%);
    }
    
    section {
        background-color: var(--block);
        height: 500px;
        padding-top: 40px;
        margin: 15px;
        box-shadow: 10px 10px 10px DimGray;
    }
    
    a {
        color: Indigo;
        font-size: 150%;
        padding: 10px;
        font-weight: bold;
    }
    
    a:hover {
        background-color: Indigo;
        color: white;
    }
    
    img,
    table {
        border: 1px solid;
        width: 80%;
        margin: 40px auto;
    }
    Podgląd strony po tym kroku (index.html)
  28. Etap 4: Skrypt PHP

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

    Krok 28: Połączenie z bazą na górze pliku i zamknięcie

    Kryteria: ,

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

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

    ok. 4 min
    Polecenie z arkusza

    Skrypt łączy się z serwerem bazy danych na localhost, użytkownik root bez hasła, baza danych o nazwie wynajem. Po wykonaniu operacji na bazie danych skrypt zamyka połączenie z serwerem.

    Cały kod rozmawiający z bazą stoi na górze cennik.php, przed HTML-em - strona najpierw pobiera dane, a potem je wypisuje, i połączenie jest zamknięte, zanim przeglądarka dostanie pierwszy znacznik.

    • new PDO(...) - serwer localhost, baza wynajem, kodowanie utf8mb4, użytkownik root bez hasła (R.5.1). ERRMODE_EXCEPTION - błąd bazy rzuca wyjątek, a FETCH_ASSOC - wiersze przychodzą z nazwami kolumn,
    • $pdo = null - PDO zamyka połączenie, gdy znika odwołanie do obiektu; stoi na końcu bloku, więc pozostanie ostatnią operacją na bazie (R.5.2),
    • try / catch (PDOException ...) - gdy baza nie działa, strona pokaże zwykłe zdanie zamiast komunikatu PHP ze szczegółami serwera.

    PDO zamiast mysqli z tabeli 1 - klucz przyjmuje obie biblioteki (uwaga przy R.5). Od tego kroku podgląd to wynik prawdziwego uruchomienia cennik.php.

    cennik.php PHP zmienione: 12 linii
    <?php
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=wynajem;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $pdo = null;    // zamknięcie połączenia - ostatnia operacja na bazie
    } catch (PDOException $exception) {
        $databaseError = 'Cennik jest chwilowo niedostępny. Spróbuj odświeżyć stronę za chwilę.';
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Wynajem pokoi</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Pensjonat pod dobrym humorem</h1>
        </header>
        <main>
            <section>
                <a href="index.html">GŁÓWNA</a>
                <img src="1.jpg" alt="pokoje">
            </section>
            <section>
                <a href="cennik.php" aria-current="page">CENNIK</a>
                <table>
                </table>
            </section>
            <section>
                <a href="kalkulator.html">KALKULATOR</a>
                <img src="3.jpg" alt="pokoje">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (cennik.php)
  29. Krok 29: Zapytanie 1 do bazy

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

    Skrypt wysyła do bazy danych zapytanie 1

    Zapytanie 1 nie ma danych od użytkownika, więc wystarczy query. fetchAll() zwraca od razu całą listę pokoi - tablicę wierszy z kluczami id, nazwa, cena. W catch lista dostaje wartość pustą, żeby HTML niżej nie trafił na niezdefiniowaną zmienną (R.5.3). Tabela jest jeszcze pusta.

    cennik.php PHP zmienione: 4 linie
    <?php
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=wynajem;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        // zapytanie 1 - cennik pokoi
        $rooms = $pdo->query('SELECT id, nazwa, cena FROM pokoje')->fetchAll();
    
        $pdo = null;    // zamknięcie połączenia - ostatnia operacja na bazie
    } catch (PDOException $exception) {
        $rooms = [];
        $databaseError = 'Cennik jest chwilowo niedostępny. Spróbuj odświeżyć stronę za chwilę.';
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Wynajem pokoi</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Pensjonat pod dobrym humorem</h1>
        </header>
        <main>
            <section>
                <a href="index.html">GŁÓWNA</a>
                <img src="1.jpg" alt="pokoje">
            </section>
            <section>
                <a href="cennik.php" aria-current="page">CENNIK</a>
                <table>
                </table>
            </section>
            <section>
                <a href="kalkulator.html">KALKULATOR</a>
                <img src="3.jpg" alt="pokoje">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

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

  30. Krok 30: Każdy pokój w kolejnym wierszu tabeli

    Kryteria: ,

    R.5.4 Skrypt wyświetla dane zwrócone zapytaniem, tak że każdy wiersz jest wpisywany do kolejnych wierszy tabeli z wykorzystaniem pętli

    R.2.6 Na stronie cennika umieszczono w bloku środkowym tabelę z trzema kolumnami, zastosowano znaczniki <table>, <tr> i <td> (w HTML lub skrypcie)

    ok. 3 min
    Polecenie z arkusza

    Dane z każdego zwróconego zapytaniem wiersza wypisywane są w kolejnym wierszu tabeli

    • foreach z dwukropkiem i endforeach - w HTML-u czytelniejsze niż klamry rozrzucone między znacznikami; jeden obieg pętli to jeden wiersz <tr> z trzema komórkami <td>,
    • pola po nazwach ($room['cena']), a nie po numerach kolumn - kod nie zależy od kolejności pól w zapytaniu,
    • <?= ... ?> to skrót od <?php echo ... ?>, a funkcja e() przepuszcza każdy tekst z bazy przez htmlspecialchars - znak < albo & w nazwie pokoju nie rozbije tabeli.

    Podgląd: jednoosobowy 100, dwuosobowy 170, trzyosobowy 210 - jak na obrazie 3 (R.5.4, R.2.6).

    cennik.php PHP zmienione: 12 linii
    <?php
    function e(string|int|float|null $value): string
    {
        return htmlspecialchars((string) $value, ENT_QUOTES);
    }
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=wynajem;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        // zapytanie 1 - cennik pokoi
        $rooms = $pdo->query('SELECT id, nazwa, cena FROM pokoje')->fetchAll();
    
        $pdo = null;    // zamknięcie połączenia - ostatnia operacja na bazie
    } catch (PDOException $exception) {
        $rooms = [];
        $databaseError = 'Cennik jest chwilowo niedostępny. Spróbuj odświeżyć stronę za chwilę.';
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Wynajem pokoi</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Pensjonat pod dobrym humorem</h1>
        </header>
        <main>
            <section>
                <a href="index.html">GŁÓWNA</a>
                <img src="1.jpg" alt="pokoje">
            </section>
            <section>
                <a href="cennik.php" aria-current="page">CENNIK</a>
                <table>
    <?php foreach ($rooms as $room): ?>
                    <tr>
                        <td><?= e($room['id']) ?></td>
                        <td><?= e($room['nazwa']) ?></td>
                        <td><?= e($room['cena']) ?></td>
                    </tr>
    <?php endforeach; ?>
                </table>
            </section>
            <section>
                <a href="kalkulator.html">KALKULATOR</a>
                <img src="3.jpg" alt="pokoje">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (cennik.php)
  31. Krok 31: Pusty cennik i awaria bazy: komunikaty

    ok. 3 min

    Dodatek spoza arkusza - klucz go nie ocenia. Tabela odpowiada teraz także w dwóch sytuacjach, których obraz 3 nie pokazuje:

    • awaria bazy (catch) - wiersz z komunikatem i role="alert" (czytnik ekranu przeczyta go od razu); reszta strony działa, bo lista pokoi ma w catch wartość pustą,
    • pusta tabela pokoje - zamiast samej ramki tabeli prośba o kontakt z recepcją.

    colspan="3" rozciąga komórkę komunikatu na trzy kolumny. Sprawdzone na prawdziwym PHP: złe hasło do bazy i pusta tabela pokoje - bez ostrzeżeń PHP. Podgląd: zwykły cennik.

    cennik.php PHP zmienione: 9 linii
    <?php
    function e(string|int|float|null $value): string
    {
        return htmlspecialchars((string) $value, ENT_QUOTES);
    }
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=wynajem;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        // zapytanie 1 - cennik pokoi
        $rooms = $pdo->query('SELECT id, nazwa, cena FROM pokoje')->fetchAll();
    
        $pdo = null;    // zamknięcie połączenia - ostatnia operacja na bazie
    } catch (PDOException $exception) {
        $rooms = [];
        $databaseError = 'Cennik jest chwilowo niedostępny. Spróbuj odświeżyć stronę za chwilę.';
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Wynajem pokoi</title>
        <link rel="stylesheet" href="styl2.css">
    </head>
    <body>
        <header>
            <h1>Pensjonat pod dobrym humorem</h1>
        </header>
        <main>
            <section>
                <a href="index.html">GŁÓWNA</a>
                <img src="1.jpg" alt="pokoje">
            </section>
            <section>
                <a href="cennik.php" aria-current="page">CENNIK</a>
                <table>
    <?php if (isset($databaseError)): ?>
                    <tr>
                        <td colspan="3" role="alert"><?= e($databaseError) ?></td>
                    </tr>
    <?php elseif ($rooms === []): ?>
                    <tr>
                        <td colspan="3">Cennik jest pusty - zapytaj w recepcji.</td>
                    </tr>
    <?php endif; ?>
    <?php foreach ($rooms as $room): ?>
                    <tr>
                        <td><?= e($room['id']) ?></td>
                        <td><?= e($room['nazwa']) ?></td>
                        <td><?= e($room['cena']) ?></td>
                    </tr>
    <?php endforeach; ?>
                </table>
            </section>
            <section>
                <a href="kalkulator.html">KALKULATOR</a>
                <img src="3.jpg" alt="pokoje">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

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

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

    Krok 32 · po tym etapie masz 33 z 33 kryteriów (pkt)

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

    ok. 3 min

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

    wersja podstawowawersja nowoczesna
    układfloat: left bloków i clear stopki<main> z grid-template-columns: repeat(3, 30%)
    szerokość bloku30% + 2 × 15 px marginesukolumna 30%, blok o 30 px węższy
    kolorywpisane w regułyzmienne CSS
    zapytanie 1SELECT *lista pól id, nazwa, cena
    bibliotekamysqli (tabela 1 arkusza)PDO z wyjątkami
    gdzie jest zapytanieblok PHP wewnątrz tabelijeden blok na górze cennik.php
    wiersz tabeli$row[0], $row[1], $row[2]$room['nazwa'] i e()
    pusta tabela, awaria bazypusta ramka, ostrzeżenia PHPkomunikaty

    Pomiar w Chrome przy oknie 1280 px: kolumna ma 373 px, blok 343 px (o 30 px mniej - marginesy), wszystkie trzy w jednym rzędzie, bez poziomego paska.

    Dane logowania do bazy w prawdziwym projekcie trzyma się zwykle w osobnym pliku (np. config.php), ale klucz sprawdza połączenie w kodzie strony - tu cały kod PHP zostaje w cennik.php.

    Na egzaminie wersja podstawowa trzyma się funkcji z tabeli 1 arkusza i łatwiej ją napisać bez dokumentacji pod ręką. Nowoczesna jest odporna na awarię bazy i dziwne znaki w danych. Obie biblioteki klucz przyjmuje.

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

  33. Etap 6: Oddanie pracy

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

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

    ok. 5 min
    Polecenie z arkusza

    Po zakończeniu pracy utwórz w folderze z numerem, którym został podpisany arkusz, 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 folderze powinny się znajdować pliki: 1.jpg, 2.jpg, 3.jpg, cennik.php, index.html, kalkulator.html, kw1.jpg, kw2.jpg, kw3.jpg, kw4.jpg kw5.jpg, kwerendy.txt, przeglądarka.txt, styl2.css, import.png, ewentualnie inne przygotowane pliki.

    W przeglądarka.txt nazwa przeglądarki, w której sprawdzana była witryna przez http://localhost/.... Pliki BMP z archiwum nie są potrzebne. 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 30.

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.