Serwis używa plików cookies do analizy ruchu i poprawy działania. Szczegóły
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.
Suwak i strzałki obok niego - albo ←→ na klawiaturze - przechodzą krok po kroku; wyjaśnienie, pliki i podgląd zmieniają się razem z krokiem.
Lista „Etap” przenosi od razu do wybranego etapu.
„Rozwiązuję samodzielnie” chowa rozwiązanie kroku - najpierw własna próba, potem odsłonięcie.
„Tryb prezentacji” pokazuje same kroki, bez menu strony - na rzutnik.
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.
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 PanelStart 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.
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
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.txtTekstnowy plik
-- Kwerenda 1CREATE TABLE pokoje ( id INT UNSIGNED NOT NULL, nazwa VARCHAR(20), cena FLOAT);
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.txtTekstzmienione: 3 linie
-- Kwerenda 1CREATE TABLE pokoje ( id INT UNSIGNED NOT NULL, nazwa VARCHAR(20), cena FLOAT);-- Kwerenda 2ALTER TABLE pokoje ADD PRIMARY KEY (id);
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.txtTekstzmienione: 6 linii
-- Kwerenda 1CREATE TABLE pokoje ( id INT UNSIGNED NOT NULL, nazwa VARCHAR(20), cena FLOAT);-- Kwerenda 2ALTER TABLE pokoje ADD PRIMARY KEY (id);-- Kwerenda 3INSERT INTO pokoje (id, nazwa, cena) VALUES(1, 'jednoosobowy', 100),(2, 'dwuosobowy', 170),(3, 'trzyosobowy', 210);
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.txtTekstzmienione: 3 linie
-- Kwerenda 1CREATE TABLE pokoje ( id INT UNSIGNED NOT NULL, nazwa VARCHAR(20), cena FLOAT);-- Kwerenda 2ALTER TABLE pokoje ADD PRIMARY KEY (id);-- Kwerenda 3INSERT INTO pokoje (id, nazwa, cena) VALUES(1, 'jednoosobowy', 100),(2, 'dwuosobowy', 170),(3, 'trzyosobowy', 210);-- Kwerenda 4ALTER TABLE rezerwacje ADD FOREIGN KEY (id_pok) REFERENCES pokoje (id);
Podgląd strony po tym kroku
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.txtTekstzmienione: 3 linie
-- Kwerenda 1CREATE TABLE pokoje ( id INT UNSIGNED NOT NULL, nazwa VARCHAR(20), cena FLOAT);-- Kwerenda 2ALTER TABLE pokoje ADD PRIMARY KEY (id);-- Kwerenda 3INSERT INTO pokoje (id, nazwa, cena) VALUES(1, 'jednoosobowy', 100),(2, 'dwuosobowy', 170),(3, 'trzyosobowy', 210);-- Kwerenda 4ALTER TABLE rezerwacje ADD FOREIGN KEY (id_pok) REFERENCES pokoje (id);-- Kwerenda 5SELECT id_pok, SUM(liczba_dn) FROM rezerwacje GROUP BY id_pok;
Podgląd strony po tym kroku
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.txtTekstzmienione: 3 linie
-- Kwerenda 1CREATE TABLE pokoje ( id INT UNSIGNED NOT NULL, nazwa VARCHAR(20), cena FLOAT);-- Kwerenda 2ALTER TABLE pokoje ADD PRIMARY KEY (id);-- Kwerenda 3INSERT INTO pokoje (id, nazwa, cena) VALUES(1, 'jednoosobowy', 100),(2, 'dwuosobowy', 170),(3, 'trzyosobowy', 210);-- Kwerenda 4ALTER TABLE rezerwacje ADD FOREIGN KEY (id_pok) REFERENCES pokoje (id);-- Kwerenda 5SELECT id_pok, SUM(liczba_dn) FROM rezerwacje GROUP BY id_pok;-- Kwerenda 6SELECT SUM(liczba_dn) FROM rezerwacje WHERE sezon = 'lato';
Podgląd strony po tym kroku
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.txtTekstzmienione: 3 linie
-- Kwerenda 1CREATE TABLE pokoje ( id INT UNSIGNED NOT NULL, nazwa VARCHAR(20), cena FLOAT);-- Kwerenda 2ALTER TABLE pokoje ADD PRIMARY KEY (id);-- Kwerenda 3INSERT INTO pokoje (id, nazwa, cena) VALUES(1, 'jednoosobowy', 100),(2, 'dwuosobowy', 170),(3, 'trzyosobowy', 210);-- Kwerenda 4ALTER TABLE rezerwacje ADD FOREIGN KEY (id_pok) REFERENCES pokoje (id);-- Kwerenda 5SELECT id_pok, SUM(liczba_dn) FROM rezerwacje GROUP BY id_pok;-- Kwerenda 6SELECT SUM(liczba_dn) FROM rezerwacje WHERE sezon = 'lato';-- Kwerenda 7UPDATE pokoje SET cena = cena * 1.15;
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.txtTekstzmienione: 3 linie
-- Kwerenda 1CREATE TABLE pokoje ( id INT UNSIGNED NOT NULL, nazwa VARCHAR(20), cena FLOAT);-- Kwerenda 2ALTER TABLE pokoje ADD PRIMARY KEY (id);-- Kwerenda 3INSERT INTO pokoje (id, nazwa, cena) VALUES(1, 'jednoosobowy', 100),(2, 'dwuosobowy', 170),(3, 'trzyosobowy', 210);-- Kwerenda 4ALTER TABLE rezerwacje ADD FOREIGN KEY (id_pok) REFERENCES pokoje (id);-- Kwerenda 5SELECT id_pok, SUM(liczba_dn) FROM rezerwacje GROUP BY id_pok;-- Kwerenda 6SELECT SUM(liczba_dn) FROM rezerwacje WHERE sezon = 'lato';-- Kwerenda 7UPDATE pokoje SET cena = cena * 1.15;-- Kwerenda 8CREATE USER 'najemca' IDENTIFIED BY 'n@JEM1@!';
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.sqlSQLnowy 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 */;CREATETABLE `pokoje` ( `id` int(10) unsignedNOT NULL, `nazwa` varchar(20) DEFAULT NULL, `cena` floatDEFAULT NULL,PRIMARYKEY (`id`)) ENGINE=InnoDB DEFAULTCHARSET=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 */;INSERTINTO `pokoje` VALUES (1,'jednoosobowy',115),(2,'dwuosobowy',195.5),(3,'trzyosobowy',241.5);/*!40000 ALTER TABLE `pokoje` ENABLE KEYS */;UNLOCKTABLES;---- Table structure for table `rezerwacje`--DROP TABLE IF EXISTS `rezerwacje`;/*!40101 SET @saved_cs_client = @@character_set_client */;/*!40101 SET character_set_client = utf8 */;CREATETABLE `rezerwacje` ( `id_rez` int(10) unsignedNOT NULL, `id_pok` int(10) unsignedDEFAULT NULL, `liczba_dn` int(10) unsignedDEFAULT NULL, `sezon` char(10) DEFAULT NULL,PRIMARYKEY (`id_rez`),KEY `id_pok` (`id_pok`),CONSTRAINT `rezerwacje_ibfk_1` FOREIGNKEY (`id_pok`) REFERENCES `pokoje` (`id`)) ENGINE=InnoDB DEFAULTCHARSET=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 */;INSERTINTO `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 */;UNLOCKTABLES;/*!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
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 jako1.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
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.
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.
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.
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).
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.
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.
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.
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
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).
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).
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.
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).
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.
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.
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 <i>apartament</i>, 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.
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.
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
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: Bartosz Bryniarski. 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.