Serwis używa plików cookies do analizy ruchu i poprawy działania. Szczegóły
E.14-02-20.06-SGCzerwiec 2020 · 44 kroki · ok. 85 min · 36 kryteriów z klucza
Rozwiązanie krok po kroku: Wynajem pokoi z cennikiem (Nowoczesny kod (flex, PDO))
To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza wynajem z ośmioma kwerendami i eksportem, trzy zdjęcia 200 × 200 px w odcieniach szarości oraz strony index.html, cennik.php i kalkulator.html - i tak samo spełnia każde kryterium klucza. Inna jest droga:
kontenery flex zamiast float: rząd menu stoi w znaczniku <nav>, rząd bloków w <main>, a szerokości 33% i 34% dalej są ustawione na samych blokach - nie trzeba clear,
zmienne CSS dla trzech kolorów z arkusza, baner 1 w znaczniku <header>, bloki w znacznikach <section>, jak wymaga arkusz,
PHP na PDO na górze pliku cennik.php, przed HTML-em: połączenie w bloku try, zamknięcie w finally, a w tabeli tylko pętla foreach po gotowej tablicy,
dane z bazy wypisywane przez htmlspecialchars, a gdy baza nie odpowiada - zrozumiały komunikat zamiast ostrzeżeń PHP.
Kroki bazy danych i grafiki są takie same jak w wersji podstawowej. Arkusz to E.14 z czerwca 2020 (formuła 2012, zastąpiona przez INF.03); materiały pochodzą z oryginalnego archiwum CKE egzamin2.zip, kwerendy są wykonane na MariaDB 10.4, a podgląd od kroków z PHP to wynik prawdziwego uruchomienia cennik.php w PHP 8.2.
Jak liczą się punkty. Klucz ma 36 kryteriów (R.1.1 - R.5.6), każde za 1 punkt; próg to 27 punktów. Klucz wprost przyjmuje skrypt na MySQLi albo PDO.
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-24 · po tym etapie masz 19 z 36 kryteriów (pkt)
Krok 13: Grafika: trzy obrazy 200 × 200 px w odcieniach szarości
Kryteria:
R.2.1 Przynajmniej jeden obraz z 1.jpg, 2.jpg, 3.jpg zapisano z rozmiarem 200 px (± 2 px) na 200 px (± 2 px) w odcieniach szarości
ok. 5 min
Polecenie z arkusza
Obrazy 1.bmp, 2.bmp i 3.bmp należy przygotować według wytycznych: Format JPEG. Rozmiar dokładnie 200 px na 200 px (bez zachowania proporcji). Odcienie szarości
Każdy obraz w GIMP-ie:
Obraz → Tryb → Odcienie szarości,
Obraz → Skaluj obraz, łańcuch rozpięty (bez zachowania proporcji), 200 × 200 - zdjęcia 3872 × 2592 i 1632 × 1224 px zostają ściśnięte w poziomie,
Plik → Eksportuj 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 i kodowanie
Kryteria:
R.2.2 Witrynę internetową zapisano w plikach index.html, cennik.php, kalkulator.html oraz zastosowano właściwy standard kodowania polskich znaków na przynajmniej jednej stronie
ok. 2 min
Polecenie z arkusza
Strona składa się z plików index.html, cennik.php, kalkulator.html. Standard kodowania polskich znaków
Szkielet strony index.html z <meta charset="UTF-8"> jako pierwszym elementem <head> (R.2.2) i znacznikiem viewport, dzięki któremu telefon nie pomniejsza strony. Pozostałe dwie strony będą kopiami tego pliku.
R.2.3 Nadano tytuł przynajmniej jednej stronie "Pokoje”
R.3.5 Przynajmniej jedna strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl.css formatowanie pochodzi jedynie od pliku CSS. Uwaga: kryterium to nie jest spełnione również, gdy zdający źle przypisał co najmniej jeden selektor do bloku (np. kropka zamiast #)
ok. 1 min
Polecenie z arkusza
Tytuł strony: „Pokoje”. Strona połączona z zewnętrznym arkuszem stylów o nazwie styl.css
<title>Pokoje</title> (R.2.3) i <link rel="stylesheet" href="styl.css"> - całe formatowanie idzie do tego pliku (R.3.5).
R.2.4 Układ przynajmniej jednej strony zdefiniowano dzieląc ją na bloki: banera1; obok siebie menu1, menu2, menu3; banera2; obok siebie bloki lewy, środkowy, prawy; stopka. Podział wykonany za pomocą znaczników sekcji
ok. 3 min
Polecenie z arkusza
Podział strony na bloki: banera1; obok siebie menu1, menu2, menu3; banera2; obok siebie bloki lewy, środkowy, prawy; stopka. Podział wykonany za pomocą znaczników sekcji
Każdy blok z arkusza dostaje swój znacznik:
baner 1 to nagłówek strony - <header>,
trzy menu to <section> w znaczniku <nav> (nawigacja), trzy bloki dolne to <section> w <main> (główna treść),
baner 2 to pusta <section>, stopka - <footer>.
<nav> i <main> mają klasę row - w stylach staną się kontenerami flex, które ustawią swoje bloki obok siebie. Bloki z arkusza są w znacznikach sekcji (R.2.4).
R.2.6 Na stronie index umieszczono w blokach lewym, środkowym i prawym obrazy 1, 2, 3 z tekstem alternatywnym "Gdzie obrazek?"
ok. 2 min
Polecenie z arkusza
Zawartość bloków lewego, środkowego, prawego dla strony index.html: blok lewy: obraz pierwszy z tekstem alternatywnym „Gdzie obrazek?”; blok środkowy: obraz drugi z tekstem alternatywnym „Gdzie obrazek?”; blok prawy: obraz trzeci z tekstem alternatywnym „Gdzie obrazek?”
Trzy <img> z tekstem alternatywnym z arkusza (R.2.6). Atrybuty width i height mówią przeglądarce, ile miejsca zarezerwować, zanim obraz się wczyta - strona nie „skacze” przy ładowaniu.
R.2.5 Na przynajmniej jednej stronie zapisano w banerze1 h2: "WYNAJEM POKOI”, w stopce umieszczono paragraf (znacznik <p>) oraz na stronie cennik.php w bloku środkowym umieszczono h1: "Cennik"
ok. 2 min
Polecenie z arkusza
Zawartość bloków lewego, środkowego, prawego dla strony cennik.php: blok lewy i prawy pusty; blok środkowy: nagłówek pierwszego stopnia o treści „Cennik”, tabela o trzech kolumnach wypełniona przez skrypt
Druga kopia jako cennik.php: <h1>Cennik</h1> i pusta <table>, którą wypełni skrypt. Nagłówki <h2> i <h1> oraz akapit w stopce to R.2.5.
Kroki 25-37 · po tym etapie masz 29 z 36 kryteriów (pkt)
Krok 25: Zmienne z kolorami arkusza
ok. 2 min
Polecenie z arkusza
Styl CSS zawiera cechy formatowania dla:
Arkusz używa trzech kolorów w dziewięciu miejscach. Zapisane raz jako zmienne w :root (--dark, --light, --mid) wstawia się przez var(--dark) - zmiana odcienia to jedna linia, a nazwa mówi więcej niż kod szesnastkowy.
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.2 Ustawiono wysokość banera1 i stopki na 80px, banera2 na 20px, bloków menu na 40px, pozostałych na 400px
R.4.6 Ustawiono krój czcionki Arial dla banera1 i stopki
ok. 1 min
Polecenie z arkusza
stopki: czcionka Arial, wysokość 80 px
Wysokości (R.4.2) i Arial w banerze 1 i stopce (R.4.6). display: flow-root zatrzymuje margines akapitu w stopce - bez tego „wypchnąłby” stopkę 20 px w dół i między blokami a stopką zostałby biały pasek. Klucz tego nie ocenia.
R.4.8 Ustawiono dla selektora * lub html lub body lub kontenera całej strony rozmiar czcionki 20px i wycentrowanie
ok. 1 min
Polecenie z arkusza
selektora strony: tekst wycentrowany o rozmiarze 20 px
body z wyśrodkowaniem i 20 px (R.4.8). margin: 0 zdejmuje domyślny margines 8 px - bloki dochodzą do krawędzi okna, a 100% szerokości to naprawdę cała szerokość okna. Klucz tego nie wymaga.
R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest w pełni zgodny z obrazem 2 w arkuszu
ok. 2 min
Polecenie z arkusza
Podział strony na bloki: banera1; obok siebie menu1, menu2, menu3; banera2; obok siebie bloki lewy, środkowy, prawy; stopka.
.row { display: flex; } - <nav> i <main> stają się kontenerami, które ustawiają swoje bloki w rzędzie. Baner 2 i stopka leżą poza kontenerami, więc same schodzą pod spód - bez float i bez clear.
Tabela z margin: 0 auto stoi na środku bloku (wyśrodkowanie tekstu w body jej nie przesuwa, bo tabela nie jest tekstem). Zmierzone w Chrome przy oknie 1280 px: baner 1 (90 px), rząd menu (50 px), baner 2 (20 px), rząd bloków (500 px) i stopka (80 px) leżą jedno pod drugim, szerokości 33/34/33% (R.3.1).
R.5.4 Skrypt wysyła do bazy danych zapytanie wybierające wszystkie wiersze z tabeli pokoje
ok. 2 min
Polecenie z arkusza
Wysyła do bazy danych zapytanie wybierające wszystkie wiersze z tabeli pokoje
$pdo->query('SELECT * FROM pokoje;') wysyła zapytanie (R.5.4), a fetchAll(PDO::FETCH_ASSOC) od razu odbiera wszystkie wiersze jako tablicę, w której kolumny mają nazwy: $room['nazwa'] zamiast $row[1]. Zapytanie nie ma żadnych danych od użytkownika, więc nie trzeba go przygotowywać.
R.5.5 Skrypt wyświetla wszystkie dane pobrane z bazy
R.5.6 Dane są wyświetlane w tabeli o trzech kolumnach, każdy wiersz zawiera osobny rekord
R.2.7 Na stronie zawierającej cennik umieszczono tabelę o trzech kolumnach (w skrypcie lub HTML), zastosowano znaczniki <table>, <tr>, <td> oraz ich zamknięcia
ok. 4 min
Polecenie z arkusza
Dane z każdego zwróconego zapytaniem wiersza wypisywane są w kolejnym wierszu tabeli
W miejscu tabeli zostaje sam HTML z krótkimi wstawkami PHP:
foreach ($rooms as $room) - jeden wiersz <tr> na rekord, trzy komórki <td> na numer, nazwę i cenę (R.5.5, R.5.6, R.2.7),
e() - własna funkcja na górze pliku, skrót do htmlspecialchars: znaki <, >, & i cudzysłowy z bazy trafiają na stronę jako tekst, nigdy jako znaczniki,
<?= ... ?> to skrót od <?php echo ... ?>, a składnia if: ... else: ... endif; czyta się w HTML-u łatwiej niż klamry,
$rooms = [] i $error = '' na starcie - zmienne istnieją zawsze, nawet gdy połączenie się nie uda.
W podglądzie cennik po podwyżce: 115, 195,5 i 241,5 (tabela 1 podaje 170 zł za pokój dwuosobowy, obraz 3 pokazuje 115).
R.5.3 Po wykonaniu wszystkich operacji na bazie zastosowano funkcję zamknięcia połączenia z serwerem bazy danych
ok. 2 min
Polecenie z arkusza
Po wykonaniu operacji na bazie danych skrypt zamyka połączenie z serwerem
W PDO połączenie zamyka $pdo = null - obiekt połączenia znika (R.5.3). Blok finally wykonuje się zawsze: po udanym zapytaniu i po wyjątku, więc połączenie nie zostanie otwarte przez przypadek. Dane są już w tablicy $rooms, więc HTML niżej bazy nie potrzebuje.
Skrypt łączy się z serwerem bazy danych na localhost, użytkownik root bez hasła, baza danych o nazwie wynajem
Sprawdzone na kopii pliku z nazwą bazy, której nie ma (wynajem_brak): konstruktor PDO rzuca wyjątek, catch ustawia komunikat, a strona pokazuje w bloku środkowym akapit „Cennik jest chwilowo niedostępny.” zamiast tabeli - bez ostrzeżeń PHP i bez ścieżek plików serwera, które wersja z mysqli_connect wypisałaby na ekran. Podgląd tego kroku to właśnie ten wynik; w pliku zostaje poprawna nazwa wynajem.
Krok 43 · po tym etapie masz 36 z 36 kryteriów (pkt)
Krok 43: Co daje druga wersja
ok. 3 min
Obie wersje dają ten sam wygląd i ten sam cennik, i obie spełniają wszystkie 36 kryteriów. Różnice:
wersja podstawowa
wersja nowoczesna
układ
float: left i clear: both
<nav> i <main> z display: flex
kolory
wpisane w każdej regule
zmienne CSS w :root
baza
mysqli_connect, mysqli_fetch_row, $row[1]
PDO, fetchAll, $room['nazwa']
PHP w HTML-u
pętla while z echo wewnątrz tabeli
dane na górze pliku, w tabeli tylko foreach
błąd bazy
ostrzeżenie PHP na stronie
komunikat dla ucznia
wypisywanie danych
wprost
przez e() (htmlspecialchars)
Na egzaminie wystarczy wersja podstawowa - jest krótsza i używa funkcji z tabeli 2 arkusza. Nowoczesna pokazuje, jak ten sam kod pisze się w projektach, które ktoś będzie potem rozwijał.
Krok 44 · po tym etapie masz 36 z 36 kryteriów (pkt)
Krok 44: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
Po zakończeniu pracy utwórz w folderze z numerem PESEL plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowałeś poprawność działania witryny. Nagraj płytę z rezultatami pracy.
W przeglądarka.txt wpisujesz nazwę przeglądarki. W folderze z numerem PESEL muszą być: 1.jpg, 2.jpg, 3.jpg, baza.txt, cennik.php, index.html, kalkulator.html, kw5.jpg, kw6.jpg, przeglądarka.txt, styl.css i wynajem.sql. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem PESEL.
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.