Przejdź do głównej treści
E.14-02-20.06-SGCzerwiec 2020 · 44 kroki · ok. 85 min · 36 kryteriów z klucza

Rozwiązanie krok po kroku: Wynajem pokoi z cennikiem (Nowoczesny kod (flex, PDO))

To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza wynajem z ośmioma kwerendami i eksportem, trzy zdjęcia 200 × 200 px w odcieniach szarości oraz strony index.html, cennik.php i kalkulator.html - i tak samo spełnia każde kryterium klucza. Inna jest droga:

  • kontenery flex zamiast float: rząd menu stoi w znaczniku <nav>, rząd bloków w <main>, a szerokości 33% i 34% dalej są ustawione na samych blokach - nie trzeba clear,
  • zmienne CSS dla trzech kolorów z arkusza, baner 1 w znaczniku <header>, bloki w znacznikach <section>, jak wymaga arkusz,
  • PHP na PDO na górze pliku cennik.php, przed HTML-em: połączenie w bloku try, zamknięcie w finally, a w tabeli tylko pętla foreach po gotowej tablicy,
  • dane z bazy wypisywane przez htmlspecialchars, a gdy baza nie odpowiada - zrozumiały komunikat zamiast ostrzeżeń PHP.

Kroki bazy danych i grafiki są takie same jak w wersji podstawowej. Arkusz to E.14 z czerwca 2020 (formuła 2012, zastąpiona przez INF.03); materiały pochodzą z oryginalnego archiwum CKE egzamin2.zip, kwerendy są wykonane na MariaDB 10.4, a podgląd od kroków z PHP to wynik prawdziwego uruchomienia cennik.php w PHP 8.2.

Jak liczą się punkty. Klucz ma 36 kryteriów (R.1.1 - R.5.6), każde za 1 punkt; próg to 27 punktów. Klucz wprost przyjmuje skrypt na MySQLi albo PDO.

  1. Etap 1: Baza danych

    Kroki 1-12 · po tym etapie masz 9 z 36 kryteriów (pkt)

    Krok 1: Folder zdającego i archiwum egzamin2.zip

    ok. 2 min
    Polecenie z arkusza

    Aby wykonać zadanie zaloguj się bez hasła na konto Egzamin. Na pulpicie znajduje się plik egzamin2.zip, z plikami potrzebnymi do rozwiązania zadania. Plik zabezpieczony jest hasłem MN52dc%% Na pulpicie utwórz folder i nazwij go Twoim numerem PESEL. Wszystkie pliki utworzone w czasie egzaminu umieść w tym folderze.

    Na pulpicie tworzysz folder nazwany numerem PESEL - w tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora, Bartosz Bryniarski. Archiwum egzamin2.zip rozpakowujesz hasłem MN52dc%% (wielkie M i N, na końcu dwa znaki procentu). W środku: rezerwacje.sql i trzy zdjęcia 1.bmp, 2.bmp, 3.bmp.

  2. Krok 2: Baza wynajem

    ok. 2 min
    Polecenie z arkusza

    Na podstawie obrazu 1 utwórz bazę danych o nazwie wynajem w przystawce phpMyAdmin pakietu XAMPP.

    W XAMPP Control Panel Start przy Apache i MySQL, potem http://localhost/phpmyadmin, Nowa, nazwa wynajem, porównywanie utf8mb4_polish_ci, Utwórz. Obraz 1 pokazuje dwie tabele: rezerwacje (z pliku) i pokoje (powstanie kwerendą 1), połączone polem id_pok.

  3. Krok 3: Import tabeli rezerwacje i klucz podstawowy id_rez

    ok. 3 min
    Polecenie z arkusza

    Zaimportuj tabelę rezerwacje z pliku rezerwacje.sql. Zdefiniuj klucz podstawowy dla tabeli rezerwacje na polu id_rez

    Baza wynajem, karta Import, plik rezerwacje.sql, Wykonaj - powstaje tabela rezerwacje z 10 rekordami. Plik nie definiuje klucza podstawowego, więc dodajesz go sam: tabela rezerwacje → Struktura → przy polu id_rez akcja Główny (klucz podstawowy) i potwierdzenie.

    Wszystkie pola liczbowe w pliku mają atrybut UNSIGNED (tylko liczby nieujemne). To ważne za trzy kroki - przy kluczu obcym.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 3
  4. Krok 4: Kwerenda 1: tabela pokoje

    Kryteria:

    R.1.1 Zapisano zapytanie tworzące tabelę pokoje z polami: id - liczba całkowita, nazwa - tekst, cena - liczba rzeczywista. W pliku z kwerendami istnieje zapis, np.: CREATE TABLE pokoje (`id` int, `nazwa` varchar(20), `cena` float); (możliwe inne typy pól spełniające warunki)

    ok. 3 min
    Polecenie z arkusza

    Pozostałe operacje na bazie wykonaj kwerendami SQL i zapisz w pliku o nazwie baza.txt numerując według opisu. Zapytania powinny mieć charakter uniwersalny, czyli powinny działać dla dowolnych danych wpisanych do tabeli. Do zapytań 5 i 6 wykonaj zrzuty ekranu dokumentujące ich działanie. Zrzuty powinny zawierać cały obszar ekranu, z widocznym paskiem zadań. Kwerenda 1: tworząca tabelę pokoje z następującymi polami: id, liczba całkowita dodatnia; nazwa, tekst do 20 znaków; cena, liczba rzeczywista

    Karta SQL bazy wynajem:

    • id INT UNSIGNED NOT NULL - liczba całkowita dodatnia: UNSIGNED wyklucza liczby ujemne, a NOT NULL przygotowuje pole na klucz podstawowy,
    • nazwa VARCHAR(20) - tekst do 20 znaków,
    • cena FLOAT - liczba rzeczywista (z częścią ułamkową).

    Kwerendy zapisujesz kolejno, z numerami, w pliku baza.txt - klucz sprawdza je w tym pliku (R.1.1).

    baza.txt Tekst nowy plik
    -- Kwerenda 1
    CREATE TABLE pokoje (
        id INT UNSIGNED NOT NULL,
        nazwa VARCHAR(20),
        cena FLOAT
    );
  5. Krok 5: Kwerenda 2: klucz podstawowy id

    Kryteria:

    R.1.2 Zdefiniowano w tabeli pokoje pole id jako klucz podstawowy, np.: ALTER TABLE pokoje ADD PRIMARY KEY(id); lub ustawiono pole id jako klucz podstawowy w zapytaniu R.1.1

    ok. 1 min
    Polecenie z arkusza

    Kwerenda 2: definiująca w tabeli pokoje pole id jako klucz podstawowy

    ALTER TABLE zmienia strukturę istniejącej tabeli, ADD PRIMARY KEY (id) czyni pole id kluczem podstawowym - każdy pokój ma inny numer (R.1.2).

    baza.txt Tekst zmienione: 3 linie
    -- Kwerenda 1
    CREATE TABLE pokoje (
        id INT UNSIGNED NOT NULL,
        nazwa VARCHAR(20),
        cena FLOAT
    );
    
    -- Kwerenda 2
    ALTER TABLE pokoje ADD PRIMARY KEY (id);
  6. Krok 6: Kwerenda 3: trzy pokoje z tabeli 1

    Kryteria:

    R.1.3 Zapisano zapytanie wstawiające do tabeli pokoje trzy wiersze: 1, jednoosobowy, 100; 2, dwuosobowy, 170; 3, trzyosobowy, 210. W pliku z kwerendami istnieje zapis, np.: INSERT INTO pokoje (`id`, `nazwa`, `cena`) VALUES ('1', 'jednoosobowy', '100'), ('2', 'dwuosobowy', '170'), ('3', 'trzyosobowy', '210'); możliwe również bez wymienienia nazw pól lub 3 zapytania lub przypisanie za pomocą SET Poprawnie również, gdy wprowadzono cenę pokoju dwuosobowego równą 100

    ok. 2 min
    Polecenie z arkusza

    Kwerenda 3: (lub zestaw kwerend) wstawiająca do tabeli pokoje dane z Tabeli 1

    Jedno INSERT z trzema nawiasami wartości - po jednym na wiersz tabeli 1: jednoosobowy 100, dwuosobowy 170, trzyosobowy 210. Kolejność wartości odpowiada liście kolumn w pierwszym nawiasie, tekst w apostrofach (R.1.3).

    ⚠️ Rozbieżność w arkuszu: obraz 3 (cennik po kwerendzie 7) pokazuje dla pokoju dwuosobowego cenę 115, czyli 100 + 15% - jakby wpisano 100 zł. Tabela 1 podaje 170 zł i to jest wpisane, więc po podwyżce cennik pokaże 195,5. Klucz CKE przyjmuje obie wersje: 170 i 100.

    baza.txt Tekst zmienione: 6 linii
    -- Kwerenda 1
    CREATE TABLE pokoje (
        id INT UNSIGNED NOT NULL,
        nazwa VARCHAR(20),
        cena FLOAT
    );
    
    -- Kwerenda 2
    ALTER TABLE pokoje ADD PRIMARY KEY (id);
    
    -- Kwerenda 3
    INSERT INTO pokoje (id, nazwa, cena) VALUES
    (1, 'jednoosobowy', 100),
    (2, 'dwuosobowy', 170),
    (3, 'trzyosobowy', 210);
  7. Krok 7: Kwerenda 4: klucz obcy id_pok

    Kryteria:

    R.1.4 Zapisano zapytanie definiujące klucz obcy dla tabeli rezerwacje na polu id_pok łączący z tabelą pokoje . W pliku z kwerendami istnieje zapis np.: ALTER TABLE rezerwacje ADD FOREIGN KEY (id_pok) REFERENCES pokoje(id);

    ok. 3 min
    Polecenie z arkusza

    Kwerenda 4: definiująca klucz obcy dla tabeli rezerwacje na polu id_pok łączący z tabelą pokoje

    • ALTER TABLE rezerwacje - klucz obcy dostaje tabela, w której stoi pole z numerem pokoju,
    • ADD FOREIGN KEY (id_pok) - pole w tabeli rezerwacje,
    • REFERENCES pokoje (id) - pole, na które wskazuje.

    Od teraz rezerwacja może dotyczyć tylko pokoju, który istnieje w tabeli pokoje (R.1.4).

    Typy obu pól muszą się zgadzać łącznie z UNSIGNED. Sprawdzone na tej bazie: przy polu id utworzonym jako zwykłe INT (bez UNSIGNED) to samo polecenie kończy się błędem errno: 150 "Foreign key constraint is incorrectly formed" - stąd UNSIGNED w kwerendzie 1.

    Typowe błędy

    Błąd 150 nie mówi wprost, co jest nie tak - prawie zawsze to różnica typu (INT i INT UNSIGNED), brak klucza podstawowego w tabeli pokoje albo tabela MyISAM zamiast InnoDB.

    baza.txt Tekst zmienione: 3 linie
    -- Kwerenda 1
    CREATE TABLE pokoje (
        id INT UNSIGNED NOT NULL,
        nazwa VARCHAR(20),
        cena FLOAT
    );
    
    -- Kwerenda 2
    ALTER TABLE pokoje ADD PRIMARY KEY (id);
    
    -- Kwerenda 3
    INSERT INTO pokoje (id, nazwa, cena) VALUES
    (1, 'jednoosobowy', 100),
    (2, 'dwuosobowy', 170),
    (3, 'trzyosobowy', 210);
    
    -- Kwerenda 4
    ALTER TABLE rezerwacje ADD FOREIGN KEY (id_pok) REFERENCES pokoje (id);
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Krok 8: Kwerenda 5: suma dni rezerwacji każdego pokoju

    Kryteria:

    R.1.5 Zapisano zapytanie wybierające z tabeli rezerwacje jedynie id pokoju oraz liczące łączną sumę dni jego rezerwacji. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id_pok, SUM(liczba_dn) FROM rezerwacje GROUP BY id_pok; oraz na zrzucie ekranu widoczne są jedynie pole id_pok i pole obliczonej sumy, wartości: 1, 31; 2, 11; 3, 13

    ok. 3 min
    Polecenie z arkusza

    Kwerenda 5: wybierająca z tabeli rezerwacje jedynie id pokoju oraz licząca łączną sumę dni jego rezerwacji (zrzut ekranu kw5.jpg)

    • SELECT id_pok, SUM(liczba_dn) - numer pokoju i suma dni,
    • FROM rezerwacje,
    • GROUP BY id_pok - grupowanie: rezerwacje tego samego pokoju łączą się w jeden wiersz, a SUM dodaje dni w każdej grupie osobno.

    Wynik: pokój 1 - 31 dni, pokój 2 - 11, pokój 3 - 13, jak w kluczu. Zrzut całego ekranu: kw5.jpg (R.1.5).

    Typowe błędy

    Bez GROUP BY wynikiem jest jeden wiersz: suma wszystkich dni (55) przy przypadkowym numerze pokoju.

    baza.txt Tekst zmienione: 3 linie
    -- Kwerenda 1
    CREATE TABLE pokoje (
        id INT UNSIGNED NOT NULL,
        nazwa VARCHAR(20),
        cena FLOAT
    );
    
    -- Kwerenda 2
    ALTER TABLE pokoje ADD PRIMARY KEY (id);
    
    -- Kwerenda 3
    INSERT INTO pokoje (id, nazwa, cena) VALUES
    (1, 'jednoosobowy', 100),
    (2, 'dwuosobowy', 170),
    (3, 'trzyosobowy', 210);
    
    -- Kwerenda 4
    ALTER TABLE rezerwacje ADD FOREIGN KEY (id_pok) REFERENCES pokoje (id);
    
    -- Kwerenda 5
    SELECT id_pok, SUM(liczba_dn) FROM rezerwacje GROUP BY id_pok;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Kwerenda 6: suma dni rezerwacji latem

    Kryteria:

    R.1.6 Zapisano zapytanie liczące sumę dni rezerwacji latem. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT SUM(liczba_dn) FROM rezerwacje WHERE sezon = "lato"; oraz na zrzucie ekranu widoczne jest jedynie pole obliczonej sumy, wartość 30

    ok. 2 min
    Polecenie z arkusza

    Kwerenda 6: licząca sumę dni rezerwacji latem (zrzut ekranu kw6.jpg)

    SUM(liczba_dn) z warunkiem WHERE sezon = 'lato' - bez grupowania, bo potrzebna jest jedna liczba. Letnie rezerwacje: 10 + 5 + 5 + 3 + 3 + 4 = 30 dni. Zrzut: kw6.jpg (R.1.6).

    baza.txt Tekst zmienione: 3 linie
    -- Kwerenda 1
    CREATE TABLE pokoje (
        id INT UNSIGNED NOT NULL,
        nazwa VARCHAR(20),
        cena FLOAT
    );
    
    -- Kwerenda 2
    ALTER TABLE pokoje ADD PRIMARY KEY (id);
    
    -- Kwerenda 3
    INSERT INTO pokoje (id, nazwa, cena) VALUES
    (1, 'jednoosobowy', 100),
    (2, 'dwuosobowy', 170),
    (3, 'trzyosobowy', 210);
    
    -- Kwerenda 4
    ALTER TABLE rezerwacje ADD FOREIGN KEY (id_pok) REFERENCES pokoje (id);
    
    -- Kwerenda 5
    SELECT id_pok, SUM(liczba_dn) FROM rezerwacje GROUP BY id_pok;
    
    -- Kwerenda 6
    SELECT SUM(liczba_dn) FROM rezerwacje WHERE sezon = 'lato';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 9
  10. Krok 10: Kwerenda 7: podwyżka cen o 15%

    Kryteria:

    R.1.7 Zapisano zapytanie aktualizujące cenę pokoi w tabeli pokoje , cena wzrasta o 15%. W pliku z kwerendami istnieje zapis np.: UPDATE pokoje SET cena= cena + cena*0.15; (lub cena = cena * 1.15)

    ok. 2 min
    Polecenie z arkusza

    Kwerenda 7: aktualizująca cenę pokoi w tabeli pokoje. Cena dla wszystkich pokoi powinna zostać podniesiona o 15%

    UPDATE pokoje SET cena = cena * 1.15 - nowa cena to stara razy 1,15 (100% + 15%). Bez WHERE, bo podwyżka dotyczy wszystkich pokoi. Ceny po wykonaniu: 115, 195,5 i 241,5 (R.1.7).

    Uruchom tę kwerendę raz - każde kolejne wykonanie podnosi ceny o następne 15%.

    Typowe błędy

    SET cena = cena + 15 dodaje 15 zł, a nie 15%. cena * 0.15 ustawia cenę na 15% starej, czyli obniża ją o 85%.

    baza.txt Tekst zmienione: 3 linie
    -- Kwerenda 1
    CREATE TABLE pokoje (
        id INT UNSIGNED NOT NULL,
        nazwa VARCHAR(20),
        cena FLOAT
    );
    
    -- Kwerenda 2
    ALTER TABLE pokoje ADD PRIMARY KEY (id);
    
    -- Kwerenda 3
    INSERT INTO pokoje (id, nazwa, cena) VALUES
    (1, 'jednoosobowy', 100),
    (2, 'dwuosobowy', 170),
    (3, 'trzyosobowy', 210);
    
    -- Kwerenda 4
    ALTER TABLE rezerwacje ADD FOREIGN KEY (id_pok) REFERENCES pokoje (id);
    
    -- Kwerenda 5
    SELECT id_pok, SUM(liczba_dn) FROM rezerwacje GROUP BY id_pok;
    
    -- Kwerenda 6
    SELECT SUM(liczba_dn) FROM rezerwacje WHERE sezon = 'lato';
    
    -- Kwerenda 7
    UPDATE pokoje SET cena = cena * 1.15;
  11. Krok 11: Kwerenda 8: użytkownik najemca

    Kryteria:

    R.1.8 Zapisano zapytanie tworzące użytkownika najemca z widocznym hasłem n@JEM1@! W pliku z kwerendami istnieje zapis np.: CREATE USER najemca IDENTIFIED BY "n@JEM1@!"

    ok. 2 min
    Polecenie z arkusza

    Kwerenda 8: tworząca użytkownika najemca z hasłem n@JEM1@!

    CREATE USER zakłada konto serwera bazy danych, IDENTIFIED BY - hasło n@JEM1@!, przepisane znak po znaku, w apostrofach. Arkusz nie podaje hosta, więc wystarczy sama nazwa konta (R.1.8) - serwer dopisze host %, czyli dowolny komputer; wrócę do tego w dobrych praktykach.

    baza.txt Tekst zmienione: 3 linie
    -- Kwerenda 1
    CREATE TABLE pokoje (
        id INT UNSIGNED NOT NULL,
        nazwa VARCHAR(20),
        cena FLOAT
    );
    
    -- Kwerenda 2
    ALTER TABLE pokoje ADD PRIMARY KEY (id);
    
    -- Kwerenda 3
    INSERT INTO pokoje (id, nazwa, cena) VALUES
    (1, 'jednoosobowy', 100),
    (2, 'dwuosobowy', 170),
    (3, 'trzyosobowy', 210);
    
    -- Kwerenda 4
    ALTER TABLE rezerwacje ADD FOREIGN KEY (id_pok) REFERENCES pokoje (id);
    
    -- Kwerenda 5
    SELECT id_pok, SUM(liczba_dn) FROM rezerwacje GROUP BY id_pok;
    
    -- Kwerenda 6
    SELECT SUM(liczba_dn) FROM rezerwacje WHERE sezon = 'lato';
    
    -- Kwerenda 7
    UPDATE pokoje SET cena = cena * 1.15;
    
    -- Kwerenda 8
    CREATE USER 'najemca' IDENTIFIED BY 'n@JEM1@!';
  12. Krok 12: Eksport bazy do wynajem.sql

    Kryteria:

    R.1.9 Wyeksportowano bazę lub tabele pokoje i rezerwacje do pliku wynajem.sql . Czas generowania wpisany w nagłówku pliku jest zgodny z datą i godziną egzaminu

    ok. 2 min
    Polecenie z arkusza

    Wyeksportuj bazę danych do pliku wynajem.sql

    Zaznacz bazę wynajem, karta Eksport, format SQL, Wykonaj - plik wynajem.sql przenieś do folderu z numerem PESEL. Ma obie tabele z kluczami (także obcym) i dane po podwyżce.

    Klucz sprawdza linię „Czas generowania:” w nagłówku eksportu phpMyAdmin - data i godzina muszą zgadzać się z egzaminem (R.1.9). Plik w tym kroku wygenerował mysqldump z tej samej bazy; czas powstania stoi w ostatniej linii: -- Dump completed on 2026-11-10 10:16:23.

    wynajem.sql SQL nowy plik
    -- MariaDB dump 10.19  Distrib 10.4.27-MariaDB, for Win64 (AMD64)
    --
    -- Host: 127.0.0.1    Database: wynajem
    -- ------------------------------------------------------
    -- Server version	10.4.27-MariaDB
    
    /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
    /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
    /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
    /*!40101 SET NAMES utf8mb4 */;
    /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
    /*!40103 SET TIME_ZONE='+00:00' */;
    /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
    /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
    /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
    /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
    
    --
    -- Table structure for table `pokoje`
    --
    
    DROP TABLE IF EXISTS `pokoje`;
    /*!40101 SET @saved_cs_client     = @@character_set_client */;
    /*!40101 SET character_set_client = utf8 */;
    CREATE TABLE `pokoje` (
      `id` int(10) unsigned NOT NULL,
      `nazwa` varchar(20) DEFAULT NULL,
      `cena` float DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_polish_ci;
    /*!40101 SET character_set_client = @saved_cs_client */;
    
    --
    -- Dumping data for table `pokoje`
    --
    
    LOCK TABLES `pokoje` WRITE;
    /*!40000 ALTER TABLE `pokoje` DISABLE KEYS */;
    INSERT INTO `pokoje` VALUES (1,'jednoosobowy',115),(2,'dwuosobowy',195.5),(3,'trzyosobowy',241.5);
    /*!40000 ALTER TABLE `pokoje` ENABLE KEYS */;
    UNLOCK TABLES;
    
    --
    -- Table structure for table `rezerwacje`
    --
    
    DROP TABLE IF EXISTS `rezerwacje`;
    /*!40101 SET @saved_cs_client     = @@character_set_client */;
    /*!40101 SET character_set_client = utf8 */;
    CREATE TABLE `rezerwacje` (
      `id_rez` int(10) unsigned NOT NULL,
      `id_pok` int(10) unsigned DEFAULT NULL,
      `liczba_dn` int(10) unsigned DEFAULT NULL,
      `sezon` char(10) DEFAULT NULL,
      PRIMARY KEY (`id_rez`),
      KEY `id_pok` (`id_pok`),
      CONSTRAINT `rezerwacje_ibfk_1` FOREIGN KEY (`id_pok`) REFERENCES `pokoje` (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_polish_ci;
    /*!40101 SET character_set_client = @saved_cs_client */;
    
    --
    -- Dumping data for table `rezerwacje`
    --
    
    LOCK TABLES `rezerwacje` WRITE;
    /*!40000 ALTER TABLE `rezerwacje` DISABLE KEYS */;
    INSERT INTO `rezerwacje` VALUES (1,1,10,'lato'),(2,2,2,'zima'),(3,1,5,'lato'),(4,2,6,'zima'),(5,1,5,'lato'),(6,3,9,'zima'),(7,1,8,'zima'),(8,2,3,'lato'),(9,1,3,'lato'),(10,3,4,'lato');
    /*!40000 ALTER TABLE `rezerwacje` ENABLE KEYS */;
    UNLOCK TABLES;
    /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
    
    /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
    /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
    /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
    /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
    /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
    /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
    /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
    
    -- Dump completed on 2026-11-10 10:16:23
  13. Etap 2: Grafika i strona HTML

    Kroki 13-24 · po tym etapie masz 19 z 36 kryteriów (pkt)

    Krok 13: Grafika: trzy obrazy 200 × 200 px w odcieniach szarości

    Kryteria:

    R.2.1 Przynajmniej jeden obraz z 1.jpg, 2.jpg, 3.jpg zapisano z rozmiarem 200 px (± 2 px) na 200 px (± 2 px) w odcieniach szarości

    ok. 5 min
    Polecenie z arkusza

    Obrazy 1.bmp, 2.bmp i 3.bmp należy przygotować według wytycznych: Format JPEG. Rozmiar dokładnie 200 px na 200 px (bez zachowania proporcji). Odcienie szarości

    Każdy obraz w GIMP-ie:

    • Obraz → Tryb → Odcienie szarości,
    • Obraz → Skaluj obraz, łańcuch rozpięty (bez zachowania proporcji), 200 × 200 - zdjęcia 3872 × 2592 i 1632 × 1224 px zostają ściśnięte w poziomie,
    • Plik → Eksportuj jako 1.jpg (potem 2.jpg, 3.jpg).

    Klucz wymaga poprawnego co najmniej jednego obrazu (R.2.1), ale strona używa wszystkich trzech.

    Typowe błędy

    Złączony łańcuch da 200 × 134 px - proporcje zostaną, ale rozmiar nie będzie kwadratem. Kolory → Desaturacja daje szary obraz zapisany nadal jako RGB - tryb Odcienie szarości zapisuje JPEG z jednym kanałem.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 13
  14. Krok 14: Plik index.html i kodowanie

    Kryteria:

    R.2.2 Witrynę internetową zapisano w plikach index.html, cennik.php, kalkulator.html oraz zastosowano właściwy standard kodowania polskich znaków na przynajmniej jednej stronie

    ok. 2 min
    Polecenie z arkusza

    Strona składa się z plików index.html, cennik.php, kalkulator.html. Standard kodowania polskich znaków

    Szkielet strony index.html z <meta charset="UTF-8"> jako pierwszym elementem <head> (R.2.2) i znacznikiem viewport, dzięki któremu telefon nie pomniejsza strony. Pozostałe dwie strony będą kopiami tego pliku.

    index.html HTML nowy plik
    <!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 (index.html)
  15. Krok 15: Tytuł i arkusz stylów

    Kryteria: ,

    R.2.3 Nadano tytuł przynajmniej jednej stronie "Pokoje”

    R.3.5 Przynajmniej jedna strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl.css formatowanie pochodzi jedynie od pliku CSS. 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

    Tytuł strony: „Pokoje”. Strona połączona z zewnętrznym arkuszem stylów o nazwie styl.css

    <title>Pokoje</title> (R.2.3) i <link rel="stylesheet" href="styl.css"> - całe formatowanie idzie do tego pliku (R.3.5).

    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>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  16. Krok 16: Bloki w kontenerach nav i main

    Kryteria:

    R.2.4 Układ przynajmniej jednej strony zdefiniowano dzieląc ją na bloki: banera1; obok siebie menu1, menu2, menu3; banera2; obok siebie bloki lewy, środkowy, prawy; stopka. Podział wykonany za pomocą znaczników sekcji

    ok. 3 min
    Polecenie z arkusza

    Podział strony na bloki: banera1; obok siebie menu1, menu2, menu3; banera2; obok siebie bloki lewy, środkowy, prawy; stopka. Podział wykonany za pomocą znaczników sekcji

    Każdy blok z arkusza dostaje swój znacznik:

    • baner 1 to nagłówek strony - <header>,
    • trzy menu to <section> w znaczniku <nav> (nawigacja), trzy bloki dolne to <section> w <main> (główna treść),
    • baner 2 to pusta <section>, stopka - <footer>.

    <nav> i <main> mają klasę row - w stylach staną się kontenerami flex, które ustawią swoje bloki obok siebie. Bloki z arkusza są w znacznikach sekcji (R.2.4).

    index.html HTML zmienione: 22 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="banner1">
        </header>
        <nav class="row">
            <section id="menu1">
            </section>
            <section id="menu2">
            </section>
            <section id="menu3">
            </section>
        </nav>
        <section id="banner2">
        </section>
        <main class="row">
            <section id="left">
            </section>
            <section id="middle">
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  17. Krok 17: Baner 1: nagłówek

    ok. 1 min
    Polecenie z arkusza

    Zawartość banera1: nagłówek drugiego stopnia o treści: „WYNAJEM POKOI”

    <h2> w znaczniku <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>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </header>
        <nav class="row">
            <section id="menu1">
            </section>
            <section id="menu2">
            </section>
            <section id="menu3">
            </section>
        </nav>
        <section id="banner2">
        </section>
        <main class="row">
            <section id="left">
            </section>
            <section id="middle">
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  18. Krok 18: Menu 1: odnośnik „POKOJE”

    Kryteria:

    R.3.2 Na przynajmniej jednej stronie istnieje odnośnik POKOJE, który prowadzi do pliku index.html

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku menu1: odnośnik „POKOJE” do pliku index.html

    <a href="index.html"> ze ścieżką względną (R.3.2).

    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>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </header>
        <nav class="row">
            <section id="menu1">
                <a href="index.html">POKOJE</a>
            </section>
            <section id="menu2">
            </section>
            <section id="menu3">
            </section>
        </nav>
        <section id="banner2">
        </section>
        <main class="row">
            <section id="left">
            </section>
            <section id="middle">
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  19. Krok 19: Menu 2: odnośnik „CENNIK”

    Kryteria:

    R.3.3 Na przynajmniej jednej stronie istnieje odnośnik CENNIK, który prowadzi do pliku cennik.php

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku menu2: odnośnik „CENNIK” do pliku cennik.php

    <a href="cennik.php"> ze ścieżką względną (R.3.3).

    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>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </header>
        <nav class="row">
            <section id="menu1">
                <a href="index.html">POKOJE</a>
            </section>
            <section id="menu2">
                <a href="cennik.php">CENNIK</a>
            </section>
            <section id="menu3">
            </section>
        </nav>
        <section id="banner2">
        </section>
        <main class="row">
            <section id="left">
            </section>
            <section id="middle">
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  20. Krok 20: Menu 3: odnośnik „KALKULATOR”

    Kryteria:

    R.3.4 Na przynajmniej jednej stronie istnieje odnośnik KALKULATOR, który prowadzi do pliku kalkulator.html

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku menu3: odnośnik „KALKULATOR” do pliku kalkulator.html

    <a href="kalkulator.html"> ze ścieżką względną (R.3.4).

    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>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </header>
        <nav class="row">
            <section id="menu1">
                <a href="index.html">POKOJE</a>
            </section>
            <section id="menu2">
                <a href="cennik.php">CENNIK</a>
            </section>
            <section id="menu3">
                <a href="kalkulator.html">KALKULATOR</a>
            </section>
        </nav>
        <section id="banner2">
        </section>
        <main class="row">
            <section id="left">
            </section>
            <section id="middle">
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  21. Krok 21: Stopka

    ok. 1 min
    Polecenie z arkusza

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

    Akapit <p> w <footer>; na egzaminie po dwukropku wpisujesz numer PESEL, tu stoi Bartosz Bryniarski.

    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>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </header>
        <nav class="row">
            <section id="menu1">
                <a href="index.html">POKOJE</a>
            </section>
            <section id="menu2">
                <a href="cennik.php">CENNIK</a>
            </section>
            <section id="menu3">
                <a href="kalkulator.html">KALKULATOR</a>
            </section>
        </nav>
        <section id="banner2">
        </section>
        <main class="row">
            <section id="left">
            </section>
            <section id="middle">
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  22. Krok 22: Trzy obrazy w blokach dolnych

    Kryteria:

    R.2.6 Na stronie index umieszczono w blokach lewym, środkowym i prawym obrazy 1, 2, 3 z tekstem alternatywnym "Gdzie obrazek?"

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloków lewego, środkowego, prawego dla strony index.html: blok lewy: obraz pierwszy z tekstem alternatywnym „Gdzie obrazek?”; blok środkowy: obraz drugi z tekstem alternatywnym „Gdzie obrazek?”; blok prawy: obraz trzeci z tekstem alternatywnym „Gdzie obrazek?”

    Trzy <img> z tekstem alternatywnym z arkusza (R.2.6). Atrybuty width i height mówią przeglądarce, ile miejsca zarezerwować, zanim obraz się wczyta - strona nie „skacze” przy ładowaniu.

    index.html HTML zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </header>
        <nav class="row">
            <section id="menu1">
                <a href="index.html">POKOJE</a>
            </section>
            <section id="menu2">
                <a href="cennik.php">CENNIK</a>
            </section>
            <section id="menu3">
                <a href="kalkulator.html">KALKULATOR</a>
            </section>
        </nav>
        <section id="banner2">
        </section>
        <main class="row">
            <section id="left">
                <img src="1.jpg" alt="Gdzie obrazek?" width="200" height="200">
            </section>
            <section id="middle">
                <img src="2.jpg" alt="Gdzie obrazek?" width="200" height="200">
            </section>
            <section id="right">
                <img src="3.jpg" alt="Gdzie obrazek?" width="200" height="200">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  23. Krok 23: Strona kalkulator.html

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloków lewego, środkowego, prawego dla strony kalkulator.html: blok lewy i prawy pusty; blok środkowy: napis: „strona w trakcie budowy”

    Kopia index.html jako kalkulator.html; napis stoi w akapicie <p> - tekst w znaczniku łatwiej później ostylować niż goły tekst w bloku.

    kalkulator.html HTML nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </header>
        <nav class="row">
            <section id="menu1">
                <a href="index.html">POKOJE</a>
            </section>
            <section id="menu2">
                <a href="cennik.php">CENNIK</a>
            </section>
            <section id="menu3">
                <a href="kalkulator.html">KALKULATOR</a>
            </section>
        </nav>
        <section id="banner2">
        </section>
        <main class="row">
            <section id="left">
            </section>
            <section id="middle">
                <p>strona w trakcie budowy</p>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalkulator.html)
  24. Krok 24: Strona cennik.php: nagłówek i tabela

    Kryteria:

    R.2.5 Na przynajmniej jednej stronie zapisano w banerze1 h2: "WYNAJEM POKOI”, w stopce umieszczono paragraf (znacznik <p>) oraz na stronie cennik.php w bloku środkowym umieszczono h1: "Cennik"

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloków lewego, środkowego, prawego dla strony cennik.php: blok lewy i prawy pusty; blok środkowy: nagłówek pierwszego stopnia o treści „Cennik”, tabela o trzech kolumnach wypełniona przez skrypt

    Druga kopia jako cennik.php: <h1>Cennik</h1> i pusta <table>, którą wypełni skrypt. Nagłówki <h2> i <h1> oraz akapit w stopce to R.2.5.

    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>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </header>
        <nav class="row">
            <section id="menu1">
                <a href="index.html">POKOJE</a>
            </section>
            <section id="menu2">
                <a href="cennik.php">CENNIK</a>
            </section>
            <section id="menu3">
                <a href="kalkulator.html">KALKULATOR</a>
            </section>
        </nav>
        <section id="banner2">
        </section>
        <main class="row">
            <section id="left">
            </section>
            <section id="middle">
                <h1>Cennik</h1>
                <table>
                </table>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (cennik.php)
  25. Etap 3: Styl CSS

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

    Krok 25: Zmienne z kolorami arkusza

    ok. 2 min
    Polecenie z arkusza

    Styl CSS zawiera cechy formatowania dla:

    Arkusz używa trzech kolorów w dziewięciu miejscach. Zapisane raz jako zmienne w :root (--dark, --light, --mid) wstawia się przez var(--dark) - zmiana odcienia to jedna linia, a nazwa mówi więcej niż kod szesnastkowy.

    styl.css CSS nowy plik
    :root {
        --dark: #000033;
        --light: #E0E9F1;
        --mid: #B3C6D9;
    }
    Podgląd strony po tym kroku (index.html)
  26. Krok 26: Banery i stopka: tło i biały tekst

    Kryteria:

    R.4.4 Ustawiono biały kolor czcionki dla banera1, banera2 i stopki

    ok. 1 min
    Polecenie z arkusza

    baner1, baner2, stopka: kolor tła #000033, kolor czcionki biały

    Jedna reguła dla trzech bloków (R.4.4).

    styl.css CSS zmienione: 4 linie
    :root {
        --dark: #000033;
        --light: #E0E9F1;
        --mid: #B3C6D9;
    }
    #banner1, #banner2, footer {
        background-color: var(--dark);
        color: white;
    }
    Podgląd strony po tym kroku (index.html)
  27. Krok 27: Baner 1

    ok. 1 min
    Polecenie z arkusza

    baner1: wysokość 80 px, czcionka Arial, margines wewnętrzny górny 10 px

    Po Arial stoi krój zapasowy sans-serif - gdyby Ariala nie było w systemie, przeglądarka weźmie inny bezszeryfowy zamiast domyślnego szeryfowego.

    styl.css CSS zmienione: 5 linii
    :root {
        --dark: #000033;
        --light: #E0E9F1;
        --mid: #B3C6D9;
    }
    #banner1, #banner2, footer {
        background-color: var(--dark);
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial, sans-serif;
        padding-top: 10px;
    }
    Podgląd strony po tym kroku (index.html)
  28. Krok 28: Baner 2

    ok. 1 min
    Polecenie z arkusza

    baner2: wysokość 20 px

    Pusty pasek 20 px.

    styl.css CSS zmienione: 3 linie
    :root {
        --dark: #000033;
        --light: #E0E9F1;
        --mid: #B3C6D9;
    }
    #banner1, #banner2, footer {
        background-color: var(--dark);
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial, sans-serif;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    Podgląd strony po tym kroku (index.html)
  29. Krok 29: Menu 1 i 3

    ok. 1 min
    Polecenie z arkusza

    menu1 i menu3: kolor tła #E0E9F1, wysokość 40 px, margines wewnętrzny górny 10 px, szerokość 33%

    Szerokość ustawiona na blokach - kontener flex jej nie zmieni, bo bloki razem mają dokładnie 100%.

    styl.css CSS zmienione: 6 linii
    :root {
        --dark: #000033;
        --light: #E0E9F1;
        --mid: #B3C6D9;
    }
    #banner1, #banner2, footer {
        background-color: var(--dark);
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial, sans-serif;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: var(--light);
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    Podgląd strony po tym kroku (index.html)
  30. Krok 30: Menu 2

    ok. 1 min
    Polecenie z arkusza

    menu2: kolor tła #B3C6D9, wysokość 40 px, szerokość 34%, margines wewnętrzny górny 10 px

    33% + 34% + 33% = 100%.

    styl.css CSS zmienione: 6 linii
    :root {
        --dark: #000033;
        --light: #E0E9F1;
        --mid: #B3C6D9;
    }
    #banner1, #banner2, footer {
        background-color: var(--dark);
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial, sans-serif;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: var(--light);
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    #menu2 {
        background-color: var(--mid);
        height: 40px;
        width: 34%;
        padding-top: 10px;
    }
    Podgląd strony po tym kroku (index.html)
  31. Krok 31: Bloki lewy i prawy

    ok. 1 min
    Polecenie z arkusza

    bloku lewego i prawego: kolor tła #B3C6D9, szerokość 33%, wysokość 400 px, margines wewnętrzny górny 100 px

    Jedna reguła dla dwóch bloków.

    styl.css CSS zmienione: 6 linii
    :root {
        --dark: #000033;
        --light: #E0E9F1;
        --mid: #B3C6D9;
    }
    #banner1, #banner2, footer {
        background-color: var(--dark);
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial, sans-serif;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: var(--light);
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    #menu2 {
        background-color: var(--mid);
        height: 40px;
        width: 34%;
        padding-top: 10px;
    }
    #left, #right {
        background-color: var(--mid);
        width: 33%;
        height: 400px;
        padding-top: 100px;
    }
    Podgląd strony po tym kroku (index.html)
  32. Krok 32: Blok środkowy

    Kryteria: , ,

    R.4.1 Ustawiono kolor tła dla baner1, banera2, stopki na #000033 oraz menu1, menu3, bloku środkowego #E0E9F1 oraz menu2 i bloków lewego i prawego na #B3C6D9

    R.4.3 Ustawiono szerokość menu1, menu3, lewego i prawego na 33%, menu2, środkowego na 34%

    R.4.5 Ustawiono margines wewnętrzny górny 10px (padding-top lub padding: 10px 0 0 0) dla bloków banera1 i wszystkich menu oraz na 100px dla bloków lewego, środkowego i prawego

    ok. 1 min
    Polecenie z arkusza

    bloku środkowego: kolor tła #E0E9F1, szerokość 34%, wysokość 400 px, margines wewnętrzny górny 100 px

    Tła (R.4.1), szerokości (R.4.3) i marginesy wewnętrzne (R.4.5) są kompletne.

    styl.css CSS zmienione: 6 linii
    :root {
        --dark: #000033;
        --light: #E0E9F1;
        --mid: #B3C6D9;
    }
    #banner1, #banner2, footer {
        background-color: var(--dark);
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial, sans-serif;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: var(--light);
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    #menu2 {
        background-color: var(--mid);
        height: 40px;
        width: 34%;
        padding-top: 10px;
    }
    #left, #right {
        background-color: var(--mid);
        width: 33%;
        height: 400px;
        padding-top: 100px;
    }
    #middle {
        background-color: var(--light);
        width: 34%;
        height: 400px;
        padding-top: 100px;
    }
    Podgląd strony po tym kroku (index.html)
  33. Krok 33: Stopka

    Kryteria: ,

    R.4.2 Ustawiono wysokość banera1 i stopki na 80px, banera2 na 20px, bloków menu na 40px, pozostałych na 400px

    R.4.6 Ustawiono krój czcionki Arial dla banera1 i stopki

    ok. 1 min
    Polecenie z arkusza

    stopki: czcionka Arial, wysokość 80 px

    Wysokości (R.4.2) i Arial w banerze 1 i stopce (R.4.6). display: flow-root zatrzymuje margines akapitu w stopce - bez tego „wypchnąłby” stopkę 20 px w dół i między blokami a stopką zostałby biały pasek. Klucz tego nie ocenia.

    styl.css CSS zmienione: 5 linii
    :root {
        --dark: #000033;
        --light: #E0E9F1;
        --mid: #B3C6D9;
    }
    #banner1, #banner2, footer {
        background-color: var(--dark);
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial, sans-serif;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: var(--light);
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    #menu2 {
        background-color: var(--mid);
        height: 40px;
        width: 34%;
        padding-top: 10px;
    }
    #left, #right {
        background-color: var(--mid);
        width: 33%;
        height: 400px;
        padding-top: 100px;
    }
    #middle {
        background-color: var(--light);
        width: 34%;
        height: 400px;
        padding-top: 100px;
    }
    footer {
        font-family: Arial, sans-serif;
        height: 80px;
        display: flow-root;
    }
    Podgląd strony po tym kroku (index.html)
  34. Krok 34: Odnośniki

    Kryteria:

    R.4.7 Ustawiono dla selektora a czarny kolor czcionki bez podkreślenia

    ok. 1 min
    Polecenie z arkusza

    selektora odnośnika: czarny kolor czcionki bez podkreślenia

    color: black i text-decoration: none (R.4.7).

    styl.css CSS zmienione: 4 linie
    :root {
        --dark: #000033;
        --light: #E0E9F1;
        --mid: #B3C6D9;
    }
    #banner1, #banner2, footer {
        background-color: var(--dark);
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial, sans-serif;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: var(--light);
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    #menu2 {
        background-color: var(--mid);
        height: 40px;
        width: 34%;
        padding-top: 10px;
    }
    #left, #right {
        background-color: var(--mid);
        width: 33%;
        height: 400px;
        padding-top: 100px;
    }
    #middle {
        background-color: var(--light);
        width: 34%;
        height: 400px;
        padding-top: 100px;
    }
    footer {
        font-family: Arial, sans-serif;
        height: 80px;
        display: flow-root;
    }
    a {
        color: black;
        text-decoration: none;
    }
    Podgląd strony po tym kroku (index.html)
  35. Krok 35: Cała strona

    Kryteria:

    R.4.8 Ustawiono dla selektora * lub html lub body lub kontenera całej strony rozmiar czcionki 20px i wycentrowanie

    ok. 1 min
    Polecenie z arkusza

    selektora strony: tekst wycentrowany o rozmiarze 20 px

    body z wyśrodkowaniem i 20 px (R.4.8). margin: 0 zdejmuje domyślny margines 8 px - bloki dochodzą do krawędzi okna, a 100% szerokości to naprawdę cała szerokość okna. Klucz tego nie wymaga.

    styl.css CSS zmienione: 5 linii
    :root {
        --dark: #000033;
        --light: #E0E9F1;
        --mid: #B3C6D9;
    }
    #banner1, #banner2, footer {
        background-color: var(--dark);
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial, sans-serif;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: var(--light);
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    #menu2 {
        background-color: var(--mid);
        height: 40px;
        width: 34%;
        padding-top: 10px;
    }
    #left, #right {
        background-color: var(--mid);
        width: 33%;
        height: 400px;
        padding-top: 100px;
    }
    #middle {
        background-color: var(--light);
        width: 34%;
        height: 400px;
        padding-top: 100px;
    }
    footer {
        font-family: Arial, sans-serif;
        height: 80px;
        display: flow-root;
    }
    a {
        color: black;
        text-decoration: none;
    }
    body {
        margin: 0;
        text-align: center;
        font-size: 20px;
    }
    Podgląd strony po tym kroku (index.html)
  36. Krok 36: Tabela i komórki

    Kryteria:

    R.4.9 Ustawiono dla selektora table i td obramowanie linią ciągłą 1px

    ok. 1 min
    Polecenie z arkusza

    selektora tabeli i komórki tabeli: obramowanie linią ciągłą o szerokości 1 px

    border: 1px solid (R.4.9).

    styl.css CSS zmienione: 3 linie
    :root {
        --dark: #000033;
        --light: #E0E9F1;
        --mid: #B3C6D9;
    }
    #banner1, #banner2, footer {
        background-color: var(--dark);
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial, sans-serif;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: var(--light);
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    #menu2 {
        background-color: var(--mid);
        height: 40px;
        width: 34%;
        padding-top: 10px;
    }
    #left, #right {
        background-color: var(--mid);
        width: 33%;
        height: 400px;
        padding-top: 100px;
    }
    #middle {
        background-color: var(--light);
        width: 34%;
        height: 400px;
        padding-top: 100px;
    }
    footer {
        font-family: Arial, sans-serif;
        height: 80px;
        display: flow-root;
    }
    a {
        color: black;
        text-decoration: none;
    }
    body {
        margin: 0;
        text-align: center;
        font-size: 20px;
    }
    table, td {
        border: 1px solid;
    }
    Podgląd strony po tym kroku (index.html)
  37. Krok 37: Układ: kontenery flex

    Kryteria:

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest w pełni zgodny z obrazem 2 w arkuszu

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: banera1; obok siebie menu1, menu2, menu3; banera2; obok siebie bloki lewy, środkowy, prawy; stopka.

    .row { display: flex; } - <nav> i <main> stają się kontenerami, które ustawiają swoje bloki w rzędzie. Baner 2 i stopka leżą poza kontenerami, więc same schodzą pod spód - bez float i bez clear.

    Tabela z margin: 0 auto stoi na środku bloku (wyśrodkowanie tekstu w body jej nie przesuwa, bo tabela nie jest tekstem). Zmierzone w Chrome przy oknie 1280 px: baner 1 (90 px), rząd menu (50 px), baner 2 (20 px), rząd bloków (500 px) i stopka (80 px) leżą jedno pod drugim, szerokości 33/34/33% (R.3.1).

    styl.css CSS zmienione: 6 linii
    :root {
        --dark: #000033;
        --light: #E0E9F1;
        --mid: #B3C6D9;
    }
    #banner1, #banner2, footer {
        background-color: var(--dark);
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial, sans-serif;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: var(--light);
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    #menu2 {
        background-color: var(--mid);
        height: 40px;
        width: 34%;
        padding-top: 10px;
    }
    #left, #right {
        background-color: var(--mid);
        width: 33%;
        height: 400px;
        padding-top: 100px;
    }
    #middle {
        background-color: var(--light);
        width: 34%;
        height: 400px;
        padding-top: 100px;
    }
    footer {
        font-family: Arial, sans-serif;
        height: 80px;
        display: flow-root;
    }
    a {
        color: black;
        text-decoration: none;
    }
    body {
        margin: 0;
        text-align: center;
        font-size: 20px;
    }
    table, td {
        border: 1px solid;
    }
    table {
        margin: 0 auto;
    }
    .row {
        display: flex;
    }
    Podgląd strony po tym kroku (index.html)
  38. Etap 4: Skrypt PHP

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

    Krok 38: Połączenie PDO na górze cennik.php

    Kryteria: ,

    R.5.1 Skrypt napisano w języku PHP oraz skrypt umieszczono w pliku cennik.php oraz zawiera on przynajmniej jedną instrukcję języka zgodną ze składnią

    R.5.2 Zastosowano funkcję realizującą połączenie z serwerem bazy danych na localhost, użytkownik root, bez hasła, baza danych wynajem

    ok. 3 min
    Polecenie z arkusza

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

    Kod PHP stoi na samej górze pliku cennik.php, przed <!DOCTYPE html>: najpierw dane, potem HTML, który je tylko wypisuje.

    • new PDO('mysql:host=localhost;dbname=wynajem;charset=utf8mb4', 'root', '') - serwer localhost, baza wynajem, użytkownik root, puste hasło (R.5.1, R.5.2); charset=utf8mb4 ustala kodowanie danych,
    • PDO::ERRMODE_EXCEPTION - każdy błąd bazy rzuca wyjątek,
    • try / catch - gdy połączenie się nie uda, skrypt nie wypisze ostrzeżeń, tylko zapamięta komunikat dla ucznia w $error.

    Połączenie i nazwa bazy są w pliku cennik.php, bo tam klucz szuka skryptu - bez osobnego pliku konfiguracyjnego.

    cennik.php PHP zmienione: 9 linii
    <?php
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=wynajem;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        ]);
    } catch (PDOException $ex) {
        $error = 'Cennik jest chwilowo niedostępny.';
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </header>
        <nav class="row">
            <section id="menu1">
                <a href="index.html">POKOJE</a>
            </section>
            <section id="menu2">
                <a href="cennik.php">CENNIK</a>
            </section>
            <section id="menu3">
                <a href="kalkulator.html">KALKULATOR</a>
            </section>
        </nav>
        <section id="banner2">
        </section>
        <main class="row">
            <section id="left">
            </section>
            <section id="middle">
                <h1>Cennik</h1>
                <table>
                </table>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (cennik.php)
  39. Krok 39: Zapytanie i pobranie wszystkich wierszy

    Kryteria:

    R.5.4 Skrypt wysyła do bazy danych zapytanie wybierające wszystkie wiersze z tabeli pokoje

    ok. 2 min
    Polecenie z arkusza

    Wysyła do bazy danych zapytanie wybierające wszystkie wiersze z tabeli pokoje

    $pdo->query('SELECT * FROM pokoje;') wysyła zapytanie (R.5.4), a fetchAll(PDO::FETCH_ASSOC) od razu odbiera wszystkie wiersze jako tablicę, w której kolumny mają nazwy: $room['nazwa'] zamiast $row[1]. Zapytanie nie ma żadnych danych od użytkownika, więc nie trzeba go przygotowywać.

    cennik.php PHP zmienione: 1 linia
    <?php
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=wynajem;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        ]);
        $rooms = $pdo->query('SELECT * FROM pokoje;')->fetchAll(PDO::FETCH_ASSOC);
    } catch (PDOException $ex) {
        $error = 'Cennik jest chwilowo niedostępny.';
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </header>
        <nav class="row">
            <section id="menu1">
                <a href="index.html">POKOJE</a>
            </section>
            <section id="menu2">
                <a href="cennik.php">CENNIK</a>
            </section>
            <section id="menu3">
                <a href="kalkulator.html">KALKULATOR</a>
            </section>
        </nav>
        <section id="banner2">
        </section>
        <main class="row">
            <section id="left">
            </section>
            <section id="middle">
                <h1>Cennik</h1>
                <table>
                </table>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

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

  40. Krok 40: Tabela: pętla foreach z e()

    Kryteria: , ,

    R.5.5 Skrypt wyświetla wszystkie dane pobrane z bazy

    R.5.6 Dane są wyświetlane w tabeli o trzech kolumnach, każdy wiersz zawiera osobny rekord

    R.2.7 Na stronie zawierającej cennik umieszczono tabelę o trzech kolumnach (w skrypcie lub HTML), zastosowano znaczniki <table>, <tr>, <td> oraz ich zamknięcia

    ok. 4 min
    Polecenie z arkusza

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

    W miejscu tabeli zostaje sam HTML z krótkimi wstawkami PHP:

    • foreach ($rooms as $room) - jeden wiersz <tr> na rekord, trzy komórki <td> na numer, nazwę i cenę (R.5.5, R.5.6, R.2.7),
    • e() - własna funkcja na górze pliku, skrót do htmlspecialchars: znaki <, >, & i cudzysłowy z bazy trafiają na stronę jako tekst, nigdy jako znaczniki,
    • <?= ... ?> to skrót od <?php echo ... ?>, a składnia if: ... else: ... endif; czyta się w HTML-u łatwiej niż klamry,
    • $rooms = [] i $error = '' na starcie - zmienne istnieją zawsze, nawet gdy połączenie się nie uda.

    W podglądzie cennik po podwyżce: 115, 195,5 i 241,5 (tabela 1 podaje 170 zł za pokój dwuosobowy, obraz 3 pokazuje 115).

    cennik.php PHP zmienione: 14 linii
    <?php
    function e($value): string
    {
        return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
    }
    
    $rooms = [];
    $error = '';
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=wynajem;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        ]);
        $rooms = $pdo->query('SELECT * FROM pokoje;')->fetchAll(PDO::FETCH_ASSOC);
    } catch (PDOException $ex) {
        $error = 'Cennik jest chwilowo niedostępny.';
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </header>
        <nav class="row">
            <section id="menu1">
                <a href="index.html">POKOJE</a>
            </section>
            <section id="menu2">
                <a href="cennik.php">CENNIK</a>
            </section>
            <section id="menu3">
                <a href="kalkulator.html">KALKULATOR</a>
            </section>
        </nav>
        <section id="banner2">
        </section>
        <main class="row">
            <section id="left">
            </section>
            <section id="middle">
                <h1>Cennik</h1>
    <?php if ($error !== ''): ?>
                <p><?= e($error) ?></p>
    <?php else: ?>
                <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>
    <?php endif; ?>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (cennik.php)
  41. Krok 41: Zamknięcie połączenia w finally

    Kryteria:

    R.5.3 Po wykonaniu wszystkich operacji na bazie zastosowano funkcję zamknięcia połączenia z serwerem bazy danych

    ok. 2 min
    Polecenie z arkusza

    Po wykonaniu operacji na bazie danych skrypt zamyka połączenie z serwerem

    W PDO połączenie zamyka $pdo = null - obiekt połączenia znika (R.5.3). Blok finally wykonuje się zawsze: po udanym zapytaniu i po wyjątku, więc połączenie nie zostanie otwarte przez przypadek. Dane są już w tablicy $rooms, więc HTML niżej bazy nie potrzebuje.

    cennik.php PHP zmienione: 2 linie
    <?php
    function e($value): string
    {
        return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
    }
    
    $rooms = [];
    $error = '';
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=wynajem;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        ]);
        $rooms = $pdo->query('SELECT * FROM pokoje;')->fetchAll(PDO::FETCH_ASSOC);
    } catch (PDOException $ex) {
        $error = 'Cennik jest chwilowo niedostępny.';
    } finally {
        $pdo = null;
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </header>
        <nav class="row">
            <section id="menu1">
                <a href="index.html">POKOJE</a>
            </section>
            <section id="menu2">
                <a href="cennik.php">CENNIK</a>
            </section>
            <section id="menu3">
                <a href="kalkulator.html">KALKULATOR</a>
            </section>
        </nav>
        <section id="banner2">
        </section>
        <main class="row">
            <section id="left">
            </section>
            <section id="middle">
                <h1>Cennik</h1>
    <?php if ($error !== ''): ?>
                <p><?= e($error) ?></p>
    <?php else: ?>
                <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>
    <?php endif; ?>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

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

  42. Krok 42: Sprawdzenie: baza niedostępna

    ok. 2 min
    Polecenie z arkusza

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

    Sprawdzone na kopii pliku z nazwą bazy, której nie ma (wynajem_brak): konstruktor PDO rzuca wyjątek, catch ustawia komunikat, a strona pokazuje w bloku środkowym akapit „Cennik jest chwilowo niedostępny.” zamiast tabeli - bez ostrzeżeń PHP i bez ścieżek plików serwera, które wersja z mysqli_connect wypisałaby na ekran. Podgląd tego kroku to właśnie ten wynik; w pliku zostaje poprawna nazwa wynajem.

    cennik.php PHP zmienione: 0 linii
    <?php
    function e($value): string
    {
        return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
    }
    
    $rooms = [];
    $error = '';
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=wynajem;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        ]);
        $rooms = $pdo->query('SELECT * FROM pokoje;')->fetchAll(PDO::FETCH_ASSOC);
    } catch (PDOException $ex) {
        $error = 'Cennik jest chwilowo niedostępny.';
    } finally {
        $pdo = null;
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </header>
        <nav class="row">
            <section id="menu1">
                <a href="index.html">POKOJE</a>
            </section>
            <section id="menu2">
                <a href="cennik.php">CENNIK</a>
            </section>
            <section id="menu3">
                <a href="kalkulator.html">KALKULATOR</a>
            </section>
        </nav>
        <section id="banner2">
        </section>
        <main class="row">
            <section id="left">
            </section>
            <section id="middle">
                <h1>Cennik</h1>
    <?php if ($error !== ''): ?>
                <p><?= e($error) ?></p>
    <?php else: ?>
                <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>
    <?php endif; ?>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (cennik.php)
  43. Etap 5: Porównanie z wersją podstawową

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

    Krok 43: Co daje druga wersja

    ok. 3 min

    Obie wersje dają ten sam wygląd i ten sam cennik, i obie spełniają wszystkie 36 kryteriów. Różnice:

    wersja podstawowawersja nowoczesna
    układfloat: left i clear: both<nav> i <main> z display: flex
    kolorywpisane w każdej regulezmienne CSS w :root
    bazamysqli_connect, mysqli_fetch_row, $row[1]PDO, fetchAll, $room['nazwa']
    PHP w HTML-upętla while z echo wewnątrz tabelidane na górze pliku, w tabeli tylko foreach
    błąd bazyostrzeżenie PHP na stroniekomunikat dla ucznia
    wypisywanie danychwprostprzez e() (htmlspecialchars)

    Na egzaminie wystarczy wersja podstawowa - jest krótsza i używa funkcji z tabeli 2 arkusza. Nowoczesna pokazuje, jak ten sam kod pisze się w projektach, które ktoś będzie potem rozwijał.

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

  44. Etap 6: Oddanie pracy

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

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

    ok. 5 min
    Polecenie z arkusza

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

    W przeglądarka.txt wpisujesz nazwę przeglądarki. W folderze z numerem PESEL muszą być: 1.jpg, 2.jpg, 3.jpg, baza.txt, cennik.php, index.html, kalkulator.html, kw5.jpg, kw6.jpg, przeglądarka.txt, styl.css i wynajem.sql. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem PESEL.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

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

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.

Potwierdzenie

Informacja