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

Rozwiązanie krok po kroku: Wynajem pokoi z cennikiem (Wersja podstawowa)

Strona wynajmu pokoi: baza wynajem z tabelą rezerwacji zaimportowaną z pliku i osiem kwerend zapisanych w baza.txt - utworzenie tabeli pokoje, klucz podstawowy, dane, klucz obcy łączący rezerwacje z pokojami, suma dni rezerwacji każdego pokoju (GROUP BY), suma dni latem, podwyżka cen o 15% (UPDATE) i nowe konto bazy - oraz eksport bazy do pliku SQL. Do tego trzy zdjęcia przerobione na kwadraty 200 × 200 px w odcieniach szarości, trzy strony index.html, cennik.php i kalkulator.html z banerami, menu, trzema blokami i stopką, style w styl.css i skrypt PHP, który wypisuje cennik z bazy w tabeli.

To arkusz E.14 z czerwca 2020 - kwalifikacji formuły 2012, którą zastąpiła INF.03. Kroki idą zdanie po zdaniu za treścią arkusza - przy każdym jest polecenie z arkusza, a kod pokazuje dokładnie te linie, które je spełniają. Skrypt PHP jest napisany najprościej, funkcjami z tabeli 2 arkusza (mysqli_connect, mysqli_query, mysqli_fetch_row, mysqli_close).

To jest wersja podstawowa. W zakładce „Nowoczesny kod (flex, PDO)” jest drugi sposób rozwiązania tego samego arkusza: semantyczne znaczniki, kontenery flex, zmienne CSS i skrypt na PDO z obsługą błędów i zabezpieczeniem wypisywanych danych - obie wersje są zgodne z kluczem.

Plik rezerwacje.sql i zdjęcia pochodzą z oryginalnego archiwum CKE (załącznik do pobrania na stronie arkusza, hasło w treści zadania). Kwerendy i eksport są wykonane na MariaDB 10.4, a skrypt uruchomiony w PHP z tą bazą - podgląd kroków z PHP to prawdziwy wynik działania cennik.php.

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

  1. Etap 1: Baza danych

    Kroki 1-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-27 · 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

    ok. 1 min
    Polecenie z arkusza

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

    Najpierw komplet strony index.html - pozostałe dwie strony będą jej kopiami z inną zawartością trzech dolnych bloków. cennik.php ma rozszerzenie .php, bo będzie w nim skrypt.

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

    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. 1 min
    Polecenie z arkusza

    Standard kodowania polskich znaków

    <meta charset="UTF-8"> jako pierwszy element <head>. Trzy pliki o nazwach z arkusza i kodowanie to R.2.2.

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

    Kryteria:

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

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony: „Pokoje”

    <title>Pokoje</title> w <head>.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  17. Krok 17: Podpięcie styl.css

    Kryteria:

    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

    Strona połączona z zewnętrznym arkuszem stylów o nazwie styl.css

    <link rel="stylesheet" href="styl.css">. Całe formatowanie idzie do tego pliku (R.3.5).

    Typowe błędy

    Kropka zamiast # przy identyfikatorze bloku odbiera R.3.5, nawet gdy reszta stylów działa.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  18. Krok 18: Bloki: dwa banery, trzy menu, trzy bloki, stopka

    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. 2 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

    Osiem znaczników <section> w kolejności z arkusza i <footer>. Identyfikatory: banner1, menu1 - menu3, banner2, left, middle, right. Baner 2 zostaje pusty („Zawartość banera2: pusty”) - to pasek oddzielający menu od bloków (R.2.4).

    index.html HTML zmienione: 18 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
        </section>
        <section id="menu1">
        </section>
        <section id="menu2">
        </section>
        <section id="menu3">
        </section>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  19. Krok 19: Baner 1: nagłówek

    ok. 1 min
    Polecenie z arkusza

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

    Drugiego stopnia to <h2>.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <section id="menu1">
        </section>
        <section id="menu2">
        </section>
        <section id="menu3">
        </section>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  20. Krok 20: 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"> - ścieżka względna, sama nazwa pliku (R.3.2).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <section id="menu1">
            <a href="index.html">POKOJE</a>
        </section>
        <section id="menu2">
        </section>
        <section id="menu3">
        </section>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  21. Krok 21: 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"> - ścieżka względna, sama nazwa pliku (R.3.3).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <section id="menu1">
            <a href="index.html">POKOJE</a>
        </section>
        <section id="menu2">
            <a href="cennik.php">CENNIK</a>
        </section>
        <section id="menu3">
        </section>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  22. Krok 22: 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"> - ścieżka względna, sama nazwa pliku (R.3.4). Na wszystkich stronach menu jest takie samo.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <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>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  23. Krok 23: 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 swój numer PESEL, w tym rozwiązaniu w jego miejscu stoi Bartosz Bryniarski.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <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>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  24. Krok 24: 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?”

    W każdym bloku jeden <img>: 1.jpg, 2.jpg, 3.jpg, wszystkie z tym samym tekstem alternatywnym (R.2.6). Strona index.html jest kompletna.

    index.html HTML zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <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>
        <section id="banner2">
        </section>
        <section id="left">
            <img src="1.jpg" alt="Gdzie obrazek?">
        </section>
        <section id="middle">
            <img src="2.jpg" alt="Gdzie obrazek?">
        </section>
        <section id="right">
            <img src="3.jpg" alt="Gdzie obrazek?">
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  25. Krok 25: 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 zapisana jako kalkulator.html: obrazy usunięte, w bloku środkowym sam napis. Puste bloki zostają w kodzie - bez nich zmieniłby się układ.

    kalkulator.html HTML nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <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>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
            strona w trakcie budowy
        </section>
        <section id="right">
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalkulator.html)
  26. Krok 26: Strona cennik.php: nagłówek „Cennik”

    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”

    Druga kopia - jako cennik.php, z nagłówkiem <h1> w bloku środkowym. Nagłówki <h2> w banerze i <h1> w cenniku oraz akapit w stopce to R.2.5. Plik bez kodu PHP podgląd pokazuje wprost.

    cennik.php PHP nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <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>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
            <h1>Cennik</h1>
        </section>
        <section id="right">
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (cennik.php)
  27. Krok 27: Tabela na cennik

    ok. 1 min
    Polecenie z arkusza

    tabela o trzech kolumnach wypełniona przez skrypt

    Pusta tabela <table> pod nagłówkiem - wiersze dopisze skrypt PHP, po jednym na pokój.

    cennik.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <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>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
            <h1>Cennik</h1>
            <table>
            </table>
        </section>
        <section id="right">
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (cennik.php)
  28. Etap 3: Styl CSS

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

    Krok 28: 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

    Styl CSS zawiera cechy formatowania dla: baner1, baner2, stopka: kolor tła #000033, kolor czcionki biały

    Wspólne cechy trzech bloków w jednej regule - selektory rozdzielone przecinkiem (R.4.4).

    styl.css CSS nowy plik
    #banner1, #banner2, footer {
        background-color: #000033;
        color: white;
    }
    Podgląd strony po tym kroku (index.html)
  29. Krok 29: Baner 1

    ok. 1 min
    Polecenie z arkusza

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

    Druga reguła dla #banner1 dokłada cechy tylko tego banera. padding-top dodaje 10 px nad treścią - baner ma na stronie 90 px.

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

    ok. 1 min
    Polecenie z arkusza

    baner2: wysokość 20 px

    Pusty pasek o wysokości 20 px - widać go dzięki tłu z pierwszej reguły.

    styl.css CSS zmienione: 3 linie
    #banner1, #banner2, footer {
        background-color: #000033;
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    Podgląd strony po tym kroku (index.html)
  31. Krok 31: 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%

    Jedna reguła na dwa bloki o tych samych cechach.

    styl.css CSS zmienione: 6 linii
    #banner1, #banner2, footer {
        background-color: #000033;
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: #E0E9F1;
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    Podgląd strony po tym kroku (index.html)
  32. Krok 32: 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% - trzy menu wypełnią całą szerokość.

    styl.css CSS zmienione: 6 linii
    #banner1, #banner2, footer {
        background-color: #000033;
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: #E0E9F1;
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    #menu2 {
        background-color: #B3C6D9;
        height: 40px;
        width: 34%;
        padding-top: 10px;
    }
    Podgląd strony po tym kroku (index.html)
  33. Krok 33: 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

    Margines górny 100 px spycha obrazy w dół bloku, jak na obrazie 2.

    styl.css CSS zmienione: 6 linii
    #banner1, #banner2, footer {
        background-color: #000033;
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: #E0E9F1;
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    #menu2 {
        background-color: #B3C6D9;
        height: 40px;
        width: 34%;
        padding-top: 10px;
    }
    #left, #right {
        background-color: #B3C6D9;
        width: 33%;
        height: 400px;
        padding-top: 100px;
    }
    Podgląd strony po tym kroku (index.html)
  34. Krok 34: 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

    Komplet teł (R.4.1), szerokości 33% i 34% (R.4.3) i górnych marginesów wewnętrznych 10 i 100 px (R.4.5) jest ustawiony.

    styl.css CSS zmienione: 6 linii
    #banner1, #banner2, footer {
        background-color: #000033;
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: #E0E9F1;
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    #menu2 {
        background-color: #B3C6D9;
        height: 40px;
        width: 34%;
        padding-top: 10px;
    }
    #left, #right {
        background-color: #B3C6D9;
        width: 33%;
        height: 400px;
        padding-top: 100px;
    }
    #middle {
        background-color: #E0E9F1;
        width: 34%;
        height: 400px;
        padding-top: 100px;
    }
    Podgląd strony po tym kroku (index.html)
  35. Krok 35: 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 wszystkich bloków (R.4.2) i Arial w banerze 1 i stopce (R.4.6) są ustawione.

    styl.css CSS zmienione: 4 linie
    #banner1, #banner2, footer {
        background-color: #000033;
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: #E0E9F1;
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    #menu2 {
        background-color: #B3C6D9;
        height: 40px;
        width: 34%;
        padding-top: 10px;
    }
    #left, #right {
        background-color: #B3C6D9;
        width: 33%;
        height: 400px;
        padding-top: 100px;
    }
    #middle {
        background-color: #E0E9F1;
        width: 34%;
        height: 400px;
        padding-top: 100px;
    }
    footer {
        font-family: Arial;
        height: 80px;
    }
    Podgląd strony po tym kroku (index.html)
  36. Krok 36: Odnośniki: czarne, bez podkreślenia

    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

    Selektor a: color: black i text-decoration: none - zdejmuje podkreślenie (R.4.7). Kolor ustawiony wprost na a działa też na odwiedzone odnośniki.

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

    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

    „Selektor strony” to body - cechy dziedziczą wszystkie bloki (R.4.8). Obrazy też się wyśrodkują, bo stoją w linii tekstu.

    styl.css CSS zmienione: 4 linie
    #banner1, #banner2, footer {
        background-color: #000033;
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: #E0E9F1;
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    #menu2 {
        background-color: #B3C6D9;
        height: 40px;
        width: 34%;
        padding-top: 10px;
    }
    #left, #right {
        background-color: #B3C6D9;
        width: 33%;
        height: 400px;
        padding-top: 100px;
    }
    #middle {
        background-color: #E0E9F1;
        width: 34%;
        height: 400px;
        padding-top: 100px;
    }
    footer {
        font-family: Arial;
        height: 80px;
    }
    a {
        color: black;
        text-decoration: none;
    }
    body {
        text-align: center;
        font-size: 20px;
    }
    Podgląd strony po tym kroku (index.html)
  38. Krok 38: Tabela i komórki: obramowanie

    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 dla table i td - bez koloru ramka przyjmuje kolor tekstu. Osobne ramki tabeli i komórek dają podwójną linię, jak na obrazie 3 (R.4.9).

    styl.css CSS zmienione: 3 linie
    #banner1, #banner2, footer {
        background-color: #000033;
        color: white;
    }
    #banner1 {
        height: 80px;
        font-family: Arial;
        padding-top: 10px;
    }
    #banner2 {
        height: 20px;
    }
    #menu1, #menu3 {
        background-color: #E0E9F1;
        height: 40px;
        padding-top: 10px;
        width: 33%;
    }
    #menu2 {
        background-color: #B3C6D9;
        height: 40px;
        width: 34%;
        padding-top: 10px;
    }
    #left, #right {
        background-color: #B3C6D9;
        width: 33%;
        height: 400px;
        padding-top: 100px;
    }
    #middle {
        background-color: #E0E9F1;
        width: 34%;
        height: 400px;
        padding-top: 100px;
    }
    footer {
        font-family: Arial;
        height: 80px;
    }
    a {
        color: black;
        text-decoration: none;
    }
    body {
        text-align: center;
        font-size: 20px;
    }
    table, td {
        border: 1px solid;
    }
    Podgląd strony po tym kroku (index.html)
  39. Krok 39: Układ: menu i bloki w rzędach

    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.

    • float: left dla trzech menu i trzech bloków - każda trójka ustawia się w rzędzie,
    • clear: both dla banera 2 i stopki - schodzą pod pływające bloki.

    Zmierzone w Chrome przy szerokości okna 1280 px: baner 1 (90 px), rząd menu (33/34/33%, po 50 px), baner 2 (20 px), rząd bloków (po 500 px: 400 px treści + 100 px marginesu) i stopka (80 px) leżą jedno pod drugim bez przerw (R.3.1).

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

    Kroki 40-44 · po tym etapie masz 36 z 36 kryteriów (pkt)

    Krok 40: Połączenie z bazą wynajem

    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

    Skrypt stoi wewnątrz tabeli - to, co wypisze, trafi między <table> a </table>. mysqli_connect z tabeli 2 przyjmuje kolejno: serwer localhost, użytkownika root, puste hasło '' i nazwę bazy wynajem; zwraca połączenie, które zapamiętuje zmienna $conn (R.5.1, R.5.2).

    Strona działa tylko przez serwer: http://localhost/<folder>/cennik.php (folder w C:\xampp\htdocs), nie przez dwuklik w pliku.

    cennik.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <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>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
            <h1>Cennik</h1>
            <table>
    <?php
        $conn = mysqli_connect('localhost', 'root', '', 'wynajem');
    ?>
            </table>
        </section>
        <section id="right">
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (cennik.php)
  41. Krok 41: Zapytanie o wszystkie pokoje

    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

    mysqli_query wysyła zapytanie przez połączenie $conn. SELECT * FROM pokoje - wszystkie kolumny i wszystkie wiersze. Wynik trafia do zmiennej $result - na stronie jeszcze nic nie widać (R.5.4).

    cennik.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <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>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
            <h1>Cennik</h1>
            <table>
    <?php
        $conn = mysqli_connect('localhost', 'root', '', 'wynajem');
        $result = mysqli_query($conn, 'SELECT * FROM pokoje;');
    ?>
            </table>
        </section>
        <section id="right">
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

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

  42. Krok 42: Pętla po wierszach: pierwsza kolumna

    ok. 3 min
    Polecenie z arkusza

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

    • mysqli_fetch_row zwraca kolejny wiersz wyniku jako tablicę numeryczną ($row[0], $row[1], …), a po ostatnim - false,
    • pętla while powtarza się, dopóki są wiersze,
    • echo wypisuje wiersz tabeli <tr> z komórką <td> - na razie tylko numer pokoju.

    W podglądzie są trzy wiersze z numerami 1, 2, 3.

    cennik.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <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>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
            <h1>Cennik</h1>
            <table>
    <?php
        $conn = mysqli_connect('localhost', 'root', '', 'wynajem');
        $result = mysqli_query($conn, 'SELECT * FROM pokoje;');
        while ($row = mysqli_fetch_row($result)) {
            echo "<tr><td>$row[0]</td></tr>";
        }
    ?>
            </table>
        </section>
        <section id="right">
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (cennik.php)
  43. Krok 43: Wszystkie trzy kolumny

    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. 3 min
    Polecenie z arkusza

    tabela o trzech kolumnach wypełniona przez skrypt

    Wiersz tabeli dostaje trzy komórki: numer, nazwę i cenę - $row[0], $row[1], $row[2] w kolejności kolumn tabeli pokoje. Każdy rekord to osobny wiersz tabeli (R.5.5, R.5.6), a znaczniki <table>, <tr>, <td> mają zamknięcia (R.2.7).

    W podglądzie cennik po podwyżce: 115, 195,5 i 241,5 - przy cenie 170 zł z tabeli 1 (obraz 3 pokazuje 115, bo autor arkusza wpisał 100).

    Typowe błędy

    W napisie w cudzysłowach "$row[0]" działa bez apostrofów przy indeksie. Zapis $row["0"] też, ale $row[nazwa] z nazwą kolumny wymaga mysqli_fetch_assoc, nie fetch_row.

    cennik.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <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>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
            <h1>Cennik</h1>
            <table>
    <?php
        $conn = mysqli_connect('localhost', 'root', '', 'wynajem');
        $result = mysqli_query($conn, 'SELECT * FROM pokoje;');
        while ($row = mysqli_fetch_row($result)) {
            echo "<tr><td>$row[0]</td><td>$row[1]</td><td>$row[2]</td></tr>";
        }
    ?>
            </table>
        </section>
        <section id="right">
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (cennik.php)
  44. Krok 44: Zamknięcie połączenia

    Kryteria:

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

    ok. 1 min
    Polecenie z arkusza

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

    mysqli_close($conn) po pętli - kiedy wszystkie dane są już wypisane (R.5.3). Cennik jest gotowy.

    cennik.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <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>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
            <h1>Cennik</h1>
            <table>
    <?php
        $conn = mysqli_connect('localhost', 'root', '', 'wynajem');
        $result = mysqli_query($conn, 'SELECT * FROM pokoje;');
        while ($row = mysqli_fetch_row($result)) {
            echo "<tr><td>$row[0]</td><td>$row[1]</td><td>$row[2]</td></tr>";
        }
        mysqli_close($conn);
    ?>
            </table>
        </section>
        <section id="right">
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

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

  45. Etap 5: Dobre praktyki (poza kluczem)

    Kroki 45-46 · po tym etapie masz 36 z 36 kryteriów (pkt)

    Krok 45: Konto tylko do odczytu zamiast root bez hasła

    ok. 3 min
    Polecenie z arkusza

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

    root to administrator serwera bazy: może wszystko, we wszystkich bazach. Skrypt cennika potrzebuje tylko czytać tabelę pokoje. Gdyby w stronie znalazł się błąd pozwalający wstrzyknąć własne SQL, atakujący dostałby uprawnienia konta, na którym działa skrypt - przy root także DROP DATABASE.

    Dlatego skrypt łączy się teraz osobnym kontem z długim hasłem i jednym prawem:

    CREATE USER 'cennik'@'localhost' IDENTIFIED BY 'Xk7#pQ2v!Lm9';
    GRANT SELECT ON wynajem.pokoje TO 'cennik'@'localhost';
    

    Sprawdzone logowaniem na to konto: SELECT działa (cennik wygląda tak samo), a DROP TABLE rezerwacje i UPDATE pokoje SET cena = 1 kończą się odmową z kodem 1142. To samo dotyczy konta najemca z kwerendy 8: bez podanego hosta powstało 'najemca'@'%' - może logować się z dowolnego komputera; w prawdziwym systemie podaje się host (@'localhost') i nadaje tylko potrzebne prawa. Hasło w pliku PHP to też ryzyko - w większych projektach trzyma się je poza katalogiem strony. Stara linia zostaje w komentarzu; na egzaminie połącz się jako root bez hasła, tak jak każe arkusz - klucz sprawdza właśnie to.

    cennik.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <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>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
            <h1>Cennik</h1>
            <table>
    <?php
        // $conn = mysqli_connect('localhost', 'root', '', 'wynajem');
        $conn = mysqli_connect('localhost', 'cennik', 'Xk7#pQ2v!Lm9', 'wynajem');
        $result = mysqli_query($conn, 'SELECT * FROM pokoje;');
        while ($row = mysqli_fetch_row($result)) {
            echo "<tr><td>$row[0]</td><td>$row[1]</td><td>$row[2]</td></tr>";
        }
        mysqli_close($conn);
    ?>
            </table>
        </section>
        <section id="right">
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

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

  46. Krok 46: htmlspecialchars przy wypisywaniu nazwy

    ok. 3 min
    Polecenie z arkusza

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

    Skrypt wkleja dane z bazy prosto w kod strony. Sprawdzone: po dopisaniu do tabeli pokoju o nazwie <i>apartament</i> cennik wypisał <td><i>apartament</i></td> - przeglądarka potraktowała znaczniki z bazy jak część strony i pokazała nazwę kursywą. Tak samo zostałby wykonany wstawiony <script> - to atak XSS, a nazwy pokoi mógłby kiedyś wpisywać pracownik albo formularz.

    htmlspecialchars zamienia znaki <, >, & i cudzysłowy na encje - ten sam wiersz po zmianie wychodzi jako &lt;i&gt;apartament&lt;/i&gt;, czyli przeglądarka pokazuje dosłowny tekst. Numer i cena to liczby z pól liczbowych, więc nie niosą znaczników; tekstowe jest tylko pole nazwa. Testowy pokój usunięto - podgląd pokazuje zwykły cennik. Stara linia zostaje w komentarzu; na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.

    cennik.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Pokoje</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <section id="banner1">
            <h2>WYNAJEM POKOI</h2>
        </section>
        <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>
        <section id="banner2">
        </section>
        <section id="left">
        </section>
        <section id="middle">
            <h1>Cennik</h1>
            <table>
    <?php
        // $conn = mysqli_connect('localhost', 'root', '', 'wynajem');
        $conn = mysqli_connect('localhost', 'cennik', 'Xk7#pQ2v!Lm9', 'wynajem');
        $result = mysqli_query($conn, 'SELECT * FROM pokoje;');
        while ($row = mysqli_fetch_row($result)) {
            // echo "<tr><td>$row[0]</td><td>$row[1]</td><td>$row[2]</td></tr>";
            $name = htmlspecialchars($row[1]);
            echo "<tr><td>$row[0]</td><td>$name</td><td>$row[2]</td></tr>";
        }
        mysqli_close($conn);
    ?>
            </table>
        </section>
        <section id="right">
        </section>
        <footer>
            <p>Stronę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

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

  47. Etap 6: Oddanie pracy

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

    Krok 47: 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 43.

Podgląd

To jedno z możliwych rozwiązań. Egzaminator ocenia spełnienie kryteriów z klucza odpowiedzi, a nie zgodność z tym kodem - inna, poprawna droga też daje punkty.

Autor rozwiązania: . Licencja CC BY-NC 4.0 - kopiowanie i przeróbki do celów niekomercyjnych, z podaniem autora i źródła (link do tej strony) (zasady wykorzystania). Treść arkusza i klucza oceniania pochodzi z CKE.

Potwierdzenie

Informacja