INF.03-12-25.01-SGStyczeń 2025 · 40 kroków · ok. 87 min · 40 kryteriów z klucza
Rozwiązanie krok po kroku: Witryna internetowa piekarni (Wersja podstawowa)
Rozwiązanie buduje stronę piekarni: baza piekarnia z jedną tabelą wyroby i cztery zapytania - filtr po rodzaju, unikalne wartości posortowane malejąco (DISTINCT), wyszukiwanie fragmentu napisu (LIKE) i średnia w grupach zaokrąglona do dwóch miejsc (AVG, ROUND, GROUP BY), potem grafika złożona z dwóch zdjęć (rogal schowany pod preclem, cień, przezroczyste tło), strona piekarnia.php z obrazem na tylnym planie i półprzezroczystym nagłówkiem oraz style w styles.css. Dwa skrypty PHP: pierwszy wypełnia listę rozwijaną rodzajami wypieków z bazy, drugi po wysłaniu formularza pokazuje w tabeli wyroby wybranego rodzaju.
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ą. Skrypty są najpierw pisane najprościej (mysqli_query, mysqli_fetch_row), a na końcu zostają przerobione na wersję z prawdziwych projektów - z pokazaną na prawdziwym uruchomieniu luką SQL injection i jej naprawą.
To jest wersja podstawowa. W zakładce „Nowoczesny kod (PDO, zapytania przygotowane)” jest drugi sposób rozwiązania tego samego arkusza: kolory w zmiennych CSS i PHP na PDO z zapytaniem przygotowanym, białą listą rodzajów i zapamiętanym wyborem od pierwszej linii - obie wersje są zgodne z kluczem.
Baza i grafiki pochodzą z prawdziwego archiwum pliki1 (załącznik do arkusza, hasło w treści zadania). Zapytania i zrzuty są policzone na MariaDB 10.4 - tej samej, która jest w XAMPP. Podgląd strony to wynik prawdziwego uruchomienia kodu z danego kroku w PHP 8.2; od kroku ze Skryptem 2 - po wysłaniu formularza z rodzajem „PIECZYWO MIESZANE”, jak na ilustracji 2.
Jak liczą się punkty. Klucz ma 40 kryteriów (R.1.1 - R.5.9), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 30 punktów - można stracić 10 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-7 · po tym etapie masz 6 z 40 kryteriów (pkt)
Krok 1: Baza danych piekarnia
Kryteria:
R.1.1 Wykonany import tabeli do bazy danych piekarnia co jest udokumentowane plikiem o nazwie import w formacie PNG
ok. 2 min
Polecenie z arkusza
Utwórz bazę danych o nazwie piekarnia, z zestawem polskich znaków (np. utf8_unicode_ci).
Rozpakuj pliki1.7z z pulpitu (hasło ULeptnny!) do folderu z numerem zdającego: baza.sql, wypieki.jpg, rogal.jpg i teksty.txt. W phpMyAdmin: Nowa, nazwa piekarnia, porównywanie np. utf8_unicode_ci.
Krok 2: Import tabeli z pliku baza.sql
Kryteria:
R.1.1 Wykonany import tabeli do bazy danych piekarnia co jest udokumentowane plikiem o nazwie import w formacie PNG
ok. 2 min
Polecenie z arkusza
Z rozpakowanego archiwum zaimportuj tabelę z pliku baza.sql do utworzonej bazy.
Import → baza.sql. Tabela wyroby z ilustracji 1: 93 wyroby z rodzajem, nazwą, gramaturą (w kilogramach) i ceną. Uwaga na nazwy kolumn - zaczynają się wielką literą (Rodzaj, Nazwa, Cena).
Krok 3: Zrzut ekranu import.png
Kryteria:
R.1.1 Wykonany import tabeli do bazy danych piekarnia co jest udokumentowane plikiem o nazwie import w formacie PNG
ok. 2 min
Polecenie z arkusza
Wykonaj zrzut ekranu po imporcie. Zapisz zrzut w formacie PNG pod nazwą import. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel.
Print Screen i zapis jako import.png - na zrzucie komunikat phpMyAdmin o udanym imporcie albo tabela wyroby w drzewku bazy.
Typowe błędy
Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany.
Krok 4: Zapytanie 1: wyroby z rodzaju INNE
Kryteria: ,
R.1.2 Zapisany plik kwerendy.txt zawierający co najmniej jedno zapytanie SQL, wynikające z treści zadania
R.1.3 Wykonane zapytanie 1 wybierające jedynie pola z tabeli wyroby : Rodzaj, Nazwa, Gramatura i Cena dla wyrobów z rodzaju „INNE”. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT Rodzaj, Nazwa, Gramatura, Cena FROM wyroby WHERE Rodzaj = "INNE"; oraz wynik działania zapytania udokumentowany zrzutem, na którym widoczne są dokładnie 3 rekordy zawierające jedynie pola: Rodzaj, Nazwa, Gramatura, Cena
ok. 2 min
Polecenie z arkusza
Zapytanie 1: wybierające jedynie pola: Rodzaj, Nazwa, Gramatura i Cena dla wyrobów z rodzaju „INNE”.
Zapytanie czytasz klauzula po klauzuli:
SELECT Rodzaj, Nazwa, Gramatura, Cena - cztery kolumny, bez ID,
FROM wyroby - z jedynej tabeli bazy,
WHERE Rodzaj = "INNE" - tylko wiersze, w których rodzaj to dokładnie napis „INNE”.
Wynik: 3 wiersze (bułka tarta, pieczywo okolicznościowe i paszteciki z kapustą i grzybami). Zapytanie do kwerendy.txt, zrzut kw1.png. To zapytanie - z rodzajem z formularza zamiast „INNE” - wyśle Skrypt 2.
kwerendy.txtTekstnowy plik
-- Zapytanie 1SELECT Rodzaj, Nazwa, Gramatura, Cena FROM wyroby WHERE Rodzaj = "INNE";
Podgląd strony po tym kroku
Krok 5: Zapytanie 2: rodzaje bez powtórzeń, malejąco
Kryteria:
R.1.4 Wykonane zapytanie 2 wybierające jedynie posortowane malejąco rodzaje wyrobów. Rodzaje wyrobów nie mogą się powtarzać. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT DISTINCT Rodzaj FROM wyroby ORDER BY Rodzaj DESC; (lub GROUP BY wtedy opcjonalnie DISTINCT ) oraz wynik działania zapytania udokumentowany zrzutem, na którym widocznych jest jedynie 11 rekordów z kolumną Rodzaj
ok. 2 min
Polecenie z arkusza
Zapytanie 2: wybierające jedynie posortowane malejąco rodzaje wyrobów. Rodzaje wyrobów nie mogą się powtarzać.
SELECT DISTINCT Rodzaj - DISTINCT usuwa powtórzenia: bez niego wyszłoby 93 wierszy, po jednym na każdy wyrób, z nim - 11, po jednym na rodzaj,
ORDER BY Rodzaj DESC - malejąco, czyli alfabetycznie od końca: pierwszy jest „WYROBY CUKIERNICZE I CIASTKARSKIE”, ostatni „INNE”.
Zrzut: kw2.png. To zapytanie wyśle Skrypt 1, żeby wypełnić listę rozwijaną.
Typowe błędy
GROUP BY Rodzaj też usuwa powtórzenia i klucz to przyjmuje - ale bez ORDER BY ... DESC kolejność będzie rosnąca.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT Rodzaj, Nazwa, Gramatura, Cena FROM wyroby WHERE Rodzaj = "INNE";-- Zapytanie 2SELECT DISTINCT Rodzaj FROM wyroby ORDER BY Rodzaj DESC;
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: wyroby ze słowem „Chałka”
Kryteria:
R.1.5 Wykonane zapytanie 3 wybierające jedynie pola: ID oraz Nazwa dla wyrobów, których nazwa zawiera słowo „Chałka” . W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT ID, Nazwa FROM wyroby WHERE Nazwa LIKE '%Chałka%'; oraz wynik działania zapytania udokumentowany zrzutem, na którym widoczne są dokładnie 4 rekordy, jedynie pola: ID, Nazwa o numerach id: 57, 58, 61, 62
ok. 2 min
Polecenie z arkusza
Zapytanie 3: wybierające jedynie pola: ID oraz Nazwa dla wyrobów, których nazwa zawiera słowo „Chałka”.
LIKE '%Chałka%' - „zawiera”: znak % oznacza dowolny ciąg znaków (także pusty) przed słowem i po nim, więc pasuje i „Chałka duża”, i nazwa ze słowem w środku.
Wynik: 4 wiersze o ID 57, 58, 61 i 62, jak w kluczu. Zrzut: kw3.png.
Typowe błędy
= 'Chałka' szuka nazwy równej dokładnie temu słowu - nie zwróci nic. LIKE 'Chałka%' pominie nazwy, w których słowo nie stoi na początku.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT Rodzaj, Nazwa, Gramatura, Cena FROM wyroby WHERE Rodzaj = "INNE";-- Zapytanie 2SELECT DISTINCT Rodzaj FROM wyroby ORDER BY Rodzaj DESC;-- Zapytanie 3SELECT ID, Nazwa FROM wyroby WHERE Nazwa LIKE '%Chałka%';
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: średnia cena w każdym rodzaju
Kryteria:
R.1.6 Wykonane zapytanie 4 wybierające pole Rodzaj oraz obliczające średnią cenę dla każdej grupy wyrobów z kategorii Rodzaj, zaokrągloną do dwóch miejsc po przecinku. Nazwa (alias) kolumny ze średnią: "Średnia_cena". W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT Rodzaj, ROUND(AVG(Cena), 2) AS "Średnia_cena" FROM wyroby GROUP BY Rodzaj; (AS opcjonalnie ) oraz wynik działania zapytania udokumentowany zrzutem, na którym widocznych jest dokładnie 11 rekordów zawierających jedynie kolumny Rodzaj i alias Średnia_cena oraz pierwszy rekord ma wartości: INNE, 13.88
ok. 3 min
Polecenie z arkusza
Zapytanie 4: wybierające pole Rodzaj oraz obliczające średnią cenę dla każdej grupy wyrobów z kategorii Rodzaj, zaokrągloną do dwóch miejsc po przecinku. Obliczona średnia cena powinna mieć nadaną nazwę kolumny (alias) „Średnia cena”.
GROUP BY Rodzaj - dzieli tabelę na grupy o tym samym rodzaju; dla każdej grupy powstaje jeden wiersz wyniku,
AVG(Cena) - średnia cena w grupie, ROUND(..., 2) - zaokrąglenie do dwóch miejsc po przecinku,
AS "Średnia cena" - alias ze spacją musi stać w cudzysłowie (albo w odwróconych apostrofach), inaczej baza uzna drugie słowo za błąd składni. Klucz podaje też wariant ze znakiem podkreślenia, Średnia_cena.
Wynik: 11 wierszy, pierwsze to INNE 13.88, PIECZYWO DLA GASTRONOMII 3.80 - jak w kluczu (INNE 13.88). Zrzut: kw4.png.
Typowe błędy
AVG(Cena) bez ROUND daje długie ułamki (cena jest typu float), a bez GROUP BY - jedną średnią dla całej tabeli.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT Rodzaj, Nazwa, Gramatura, Cena FROM wyroby WHERE Rodzaj = "INNE";-- Zapytanie 2SELECT DISTINCT Rodzaj FROM wyroby ORDER BY Rodzaj DESC;-- Zapytanie 3SELECT ID, Nazwa FROM wyroby WHERE Nazwa LIKE '%Chałka%';-- Zapytanie 4SELECT Rodzaj, ROUND(AVG(Cena), 2) AS "Średnia cena" FROM wyroby GROUP BY Rodzaj;
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 8-22 · po tym etapie masz 21 z 40 kryteriów (pkt)
R.2.1 Obraz wypieki zawiera różne wypieki w tym rogala po prawej stronie. Rogal zachodzi pod precel oraz dodany cień przesunięty w prawo i w dół dla wszystkich wypieków
R.2.2 Tło obrazu jest przezroczyste oraz szerokość wynosi 1700 px, a wysokość 240 px
ok. 10 min
Polecenie z arkusza
Do grafiki z pliku wypieki.jpg należy dołączyć grafikę z pliku rogal.jpg po prawej stronie. Lewy koniec rogala zachodzi pod precel. Cechy połączonej grafiki: Tło przezroczyste. Cień przesunięty w prawo i w dół. Wymiar: szerokość 1700 px i wysokość 240 px. Nazwa pliku wypieki, format obsługujący przezroczystość.
W GIMP-ie:
otwierasz wypieki.jpg (1400 × 240), Obraz → Rozmiar płótna: szerokość 1700, wysokość 240, przesunięcie 0 - płótno rośnie w prawo; Warstwa → Warstwa do rozmiaru obrazu,
dodajesz kanał alfa i Różdżką kasujesz białe tło. Precel ma zamknięte otwory - klikasz je osobno (z Shift), bo nie łączą się z tłem; białych kropek soli nie zaznaczasz,
Plik → Otwórz jako warstwyrogal.jpg, kasujesz jego białe tło tak samo,
w oknie Warstwy przeciągasz warstwę rogala pod warstwę wypieków - dzięki temu jego lewy koniec chowa się pod preclem, a narzędziem Przesunięcie ustawiasz go po prawej stronie, jak na ilustracji 2 (tu: rogal w oryginalnej wielkości, przy prawej krawędzi),
Obraz → Spłaszcz obraz nie używasz (zabiera przezroczystość) - zamiast tego Warstwa → Scal w dół, potem Filtry → Światło i cień → Cień z dodatnimi przesunięciami X i Y (np. 8 i 8) - cień dla wszystkich wypieków naraz,
Eksportuj jakowypieki.png - PNG obsługuje przezroczystość, JPG nie.
Typowe błędy
Rogal na warstwie nad preclem zasłoni precel zamiast schować się pod nim. Cień dodany przed wklejeniem rogala obejmie tylko część wypieków - klucz wymaga cienia dla wszystkich.
Podgląd strony po tym kroku
Krok 9: Plik piekarnia.php w HTML5
Kryteria:
R.2.3 Witryna internetowa zapisana w pliku piekarnia.php oraz zapisany jawnie standard kodowania polskich znaków, deklaracja HTML5 <!DOCTYPE HTML>, zadeklarowany język witryny: polski np. <html lang="pl"> oraz nadany tytuł strony "PIEKARNIA”. Strona zawiera sekcje head i body
ok. 1 min
Polecenie z arkusza
Cechy witryny: Składa się ze strony o nazwie piekarnia.php. Zapisana w języku HTML5.
Jedna strona, piekarnia.php, zaczyna się deklaracją <!DOCTYPE html>. Dopóki nie ma w niej kodu PHP, podgląd pokazuje ją wprost.
R.2.3 Witryna internetowa zapisana w pliku piekarnia.php oraz zapisany jawnie standard kodowania polskich znaków, deklaracja HTML5 <!DOCTYPE HTML>, zadeklarowany język witryny: polski np. <html lang="pl"> oraz nadany tytuł strony "PIEKARNIA”. Strona zawiera sekcje head i body
R.2.3 Witryna internetowa zapisana w pliku piekarnia.php oraz zapisany jawnie standard kodowania polskich znaków, deklaracja HTML5 <!DOCTYPE HTML>, zadeklarowany język witryny: polski np. <html lang="pl"> oraz nadany tytuł strony "PIEKARNIA”. Strona zawiera sekcje head i body
ok. 1 min
Polecenie z arkusza
Jawnie zastosowany właściwy standard kodowania polskich znaków.
<meta charset="UTF-8"> - jako pierwszy element <head>.
R.2.3 Witryna internetowa zapisana w pliku piekarnia.php oraz zapisany jawnie standard kodowania polskich znaków, deklaracja HTML5 <!DOCTYPE HTML>, zadeklarowany język witryny: polski np. <html lang="pl"> oraz nadany tytuł strony "PIEKARNIA”. Strona zawiera sekcje head i body
ok. 1 min
Polecenie z arkusza
Tytuł strony „PIEKARNIA”, widoczny na karcie przeglądarki.
R.3.2 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styles.css formatowanie CSS pochodzi jedynie z tego arkusza. Uwaga: kryterium to nie jest spełnione również, gdy zdający źle przypisał co najmniej jeden selektor do bloku (np. kropka zamiast #)
ok. 1 min
Polecenie z arkusza
Arkusz stylów w pliku o nazwie styles.css prawidłowo połączony z kodem strony.
<link rel="stylesheet"> - uwaga na nazwę: styles.css, z „s” na końcu.
Typowe błędy
style.css albo styl.css (jak w innych arkuszach) odcina wszystkie style, a razem z nimi kryterium R.3.2.
R.2.6 Umieszczona grafika z wypiekami z tekstem alternatywnym "Produkty naszej piekarni"
ok. 1 min
Polecenie z arkusza
Obraz wypieki.png z tekstem alternatywnym o treści: „Produkty naszej piekarni” umieszczony jest na tylnym planie strony. Bloki strony zakrywają obraz.
Obraz stawiasz bezpośrednio w <body>, poza blokami - jest tłem całej strony, a nie częścią któregoś bloku. Na tylny plan przeniesie go dopiero CSS (position: fixed i z-index); na razie stoi w zwykłym miejscu.
R.2.4 Zdefiniowany układ strony dzielący ją na bloki: nawigacyjny, nagłówkowy, główny i stopki przy pomocy semantycznych znaczników sekcji języka HTML5 zgodnie z ich znaczeniem, w tym do części nagłówkowej - header, do stopki - footer. Dopuszcza się dodatkowe użycie bloków div lub section
R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z ilustracją 2 w arkuszu egzaminacyjnym. Nie należy brać pod uwagę położenia obrazu
ok. 1 min
Polecenie z arkusza
Podział strony na bloki: nawigacyjny, nagłówkowy, główny, stopki. Podział zrealizowany za pomocą semantycznych znaczników sekcji języka HTML5 tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z ilustracją 2.
Cztery znaczniki semantyczne w kolejności z ilustracji: <nav> (nawigacja jest nad nagłówkiem), <header>, <main> na blok główny i <footer>. Wszystkie bloki są jeden pod drugim na całą szerokość, więc układ nie wymaga float ani grid.
R.2.7 W bloku nawigacyjnym umieszczone 4 odnośniki o treści KWERENDA1, KWERENDA2, KWERENDA3, KWERENDA4
R.3.3 Po wybraniu przynajmniej jednego odnośnika otwiera/pobiera się plik graficzny
ok. 2 min
Polecenie z arkusza
Zawartość bloku nawigacyjnego: Cztery odnośniki o treści: KWERENDA1, KWERENDA2, KWERENDA3, KWERENDA4. Odnośniki prowadzą do kolejnych zrzutów ekranu z kwerendami.
Cztery <a> do zrzutów kw1.png - kw4.png, które leżą w tym samym folderze co strona - w href wystarczy sama nazwa pliku, a kliknięcie otworzy obraz w przeglądarce. W podglądzie kliknięcia są zablokowane.
R.2.9 Zapisany nagłówek <h1>: „WITAMY”, <h4>: "NA STRONIE PIEKARNI" oraz <h4>: „Wybierz rodzaj wypieków:"
ok. 1 min
Polecenie z arkusza
Paragraf (akapit) zawierający tekst. Tekst można skopiować z pliku teksty.txt z wypakowanego archiwum.
Otwórz teksty.txt w edytorze i skopiuj całość do <p>.
piekarnia.phpPHPzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>PIEKARNIA</title> <linkrel="stylesheet"href="styles.css"></head><body> <imgsrc="wypieki.png"alt="Produkty naszej piekarni"> <nav> <ahref="kw1.png">KWERENDA1</a> <ahref="kw2.png">KWERENDA2</a> <ahref="kw3.png">KWERENDA3</a> <ahref="kw4.png">KWERENDA4</a> </nav> <header> <h1>WITAMY</h1> <h4>NA STRONIE PIEKARNI</h4> <p>Od 31 lat oferujemy najwyższej jakości pieczywo. Naturalnie świeże, naturalnie smaczne. Pieczemy wyłącznie wypieki na naturalnym zakwasie bez polepszaczy i zagęstników. Korzystamy wyłącznie z najlepszych ziaren pochodzących z ekologicznych upraw położonych w rejonach zgierskim i ozorkowskim.</p> </header> <main> </main> <footer> </footer></body></html>
Podgląd strony po tym kroku (piekarnia.php)
Krok 19: Blok główny: nagłówek
Kryteria:
R.2.9 Zapisany nagłówek <h1>: „WITAMY”, <h4>: "NA STRONIE PIEKARNI" oraz <h4>: „Wybierz rodzaj wypieków:"
ok. 1 min
Polecenie z arkusza
Zawartość bloku głównego: Nagłówek czwartego stopnia o treści: „Wybierz rodzaj wypieków:”.
<h4>.
piekarnia.phpPHPzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>PIEKARNIA</title> <linkrel="stylesheet"href="styles.css"></head><body> <imgsrc="wypieki.png"alt="Produkty naszej piekarni"> <nav> <ahref="kw1.png">KWERENDA1</a> <ahref="kw2.png">KWERENDA2</a> <ahref="kw3.png">KWERENDA3</a> <ahref="kw4.png">KWERENDA4</a> </nav> <header> <h1>WITAMY</h1> <h4>NA STRONIE PIEKARNI</h4> <p>Od 31 lat oferujemy najwyższej jakości pieczywo. Naturalnie świeże, naturalnie smaczne. Pieczemy wyłącznie wypieki na naturalnym zakwasie bez polepszaczy i zagęstników. Korzystamy wyłącznie z najlepszych ziaren pochodzących z ekologicznych upraw położonych w rejonach zgierskim i ozorkowskim.</p> </header> <main> <h4>Wybierz rodzaj wypieków:</h4> </main> <footer> </footer></body></html>
Podgląd strony po tym kroku (piekarnia.php)
Krok 20: Formularz: lista rozwijana i przycisk
Kryteria: , ,
R.2.8 W bloku głównym umieszczony formularz z listą rozwijaną oraz przyciskiem „Wybierz”, zastosowane znaczniki <form>, <select>, <option> i przycisku (w skrypcie lub HTML)
R.3.4 Formularz wysyła dane metodą POST do tego samego pliku (poprawne również bez atrybutu action )
R.3.5 Przycisk realizuje funkcję wysłania danych z formularza (input lub button z typem submit lub button bez typu )
ok. 2 min
Polecenie z arkusza
Formularz wysyłający dane metodą bezpieczną do tego samego pliku. Pola formularza: Lista rozwijana wypełniona przez skrypt 1. Przycisk „Wybierz” wysyłający dane do skryptu 2 z formularza.
„metoda bezpieczna” w arkuszach CKE to POST - dane nie trafiają do paska adresu (w specyfikacji HTTP „bezpieczne” są metody, które niczego nie zmieniają na serwerze, czyli GET i HEAD - arkusz używa tego słowa w innym sensie); action pomijasz, więc formularz wraca do piekarnia.php (R.3.4),
<select name="type"> na razie pusty - opcje (rodzaje z bazy) dopisze Skrypt 1; pod nazwą type Skrypt 2 znajdzie wybraną wartość w $_POST,
przycisk type="submit" z napisem „Wybierz” (R.3.5).
piekarnia.phpPHPzmienione: 5 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>PIEKARNIA</title> <linkrel="stylesheet"href="styles.css"></head><body> <imgsrc="wypieki.png"alt="Produkty naszej piekarni"> <nav> <ahref="kw1.png">KWERENDA1</a> <ahref="kw2.png">KWERENDA2</a> <ahref="kw3.png">KWERENDA3</a> <ahref="kw4.png">KWERENDA4</a> </nav> <header> <h1>WITAMY</h1> <h4>NA STRONIE PIEKARNI</h4> <p>Od 31 lat oferujemy najwyższej jakości pieczywo. Naturalnie świeże, naturalnie smaczne. Pieczemy wyłącznie wypieki na naturalnym zakwasie bez polepszaczy i zagęstników. Korzystamy wyłącznie z najlepszych ziaren pochodzących z ekologicznych upraw położonych w rejonach zgierskim i ozorkowskim.</p> </header> <main> <h4>Wybierz rodzaj wypieków:</h4> <formmethod="post"> <selectname="type"> </select> <buttontype="submit">Wybierz</button> </form> </main> <footer> </footer></body></html>
Podgląd strony po tym kroku (piekarnia.php)
Krok 21: Tabela: wiersz nagłówkowy
Kryteria:
R.2.5 W bloku głównym zapisana tabela o 4 kolumnach. Pierwszy wiersz tabeli jest nagłówkowy. Zastosowane znaczniki <table>, <tr>, <th>, <td> (w skrypcie lub HTML)
ok. 2 min
Polecenie z arkusza
Tabela o czterech kolumnach zawierająca: Wiersz z komórkami nagłówkowymi: Rodzaj, Nazwa, Gramatura, Cena. Wiersze z danymi wypełnione skryptem 2.
Pierwszy wiersz z czterema <th> - w tej samej kolejności co kolumny zapytania 1. Wiersze z danymi dopisze Skrypt 2.
piekarnia.phpPHPzmienione: 8 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>PIEKARNIA</title> <linkrel="stylesheet"href="styles.css"></head><body> <imgsrc="wypieki.png"alt="Produkty naszej piekarni"> <nav> <ahref="kw1.png">KWERENDA1</a> <ahref="kw2.png">KWERENDA2</a> <ahref="kw3.png">KWERENDA3</a> <ahref="kw4.png">KWERENDA4</a> </nav> <header> <h1>WITAMY</h1> <h4>NA STRONIE PIEKARNI</h4> <p>Od 31 lat oferujemy najwyższej jakości pieczywo. Naturalnie świeże, naturalnie smaczne. Pieczemy wyłącznie wypieki na naturalnym zakwasie bez polepszaczy i zagęstników. Korzystamy wyłącznie z najlepszych ziaren pochodzących z ekologicznych upraw położonych w rejonach zgierskim i ozorkowskim.</p> </header> <main> <h4>Wybierz rodzaj wypieków:</h4> <formmethod="post"> <selectname="type"> </select> <buttontype="submit">Wybierz</button> </form> <table> <tr> <th>Rodzaj</th> <th>Nazwa</th> <th>Gramatura</th> <th>Cena</th> </tr> </table> </main> <footer> </footer></body></html>
Podgląd strony po tym kroku (piekarnia.php)
Krok 22: Stopka: autor i data
Kryteria:
R.2.10 W bloku stopki umieszczony paragraf z numerem zdającego oraz paragraf z datą egzaminu
ok. 1 min
Polecenie z arkusza
Zawartość stopki: Paragraf „AUTOR ”, dalej wstawiony numer zdającego. Paragraf „Data: ”, dalej wpisana data egzaminu.
Dwa osobne paragrafy. Na egzaminie po słowie „AUTOR” wpisujesz swój numer zdającego (PESEL), a po „Data:” - dzień egzaminu. Tu: autor rozwiązania i data jego przygotowania.
piekarnia.phpPHPzmienione: 2 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>PIEKARNIA</title> <linkrel="stylesheet"href="styles.css"></head><body> <imgsrc="wypieki.png"alt="Produkty naszej piekarni"> <nav> <ahref="kw1.png">KWERENDA1</a> <ahref="kw2.png">KWERENDA2</a> <ahref="kw3.png">KWERENDA3</a> <ahref="kw4.png">KWERENDA4</a> </nav> <header> <h1>WITAMY</h1> <h4>NA STRONIE PIEKARNI</h4> <p>Od 31 lat oferujemy najwyższej jakości pieczywo. Naturalnie świeże, naturalnie smaczne. Pieczemy wyłącznie wypieki na naturalnym zakwasie bez polepszaczy i zagęstników. Korzystamy wyłącznie z najlepszych ziaren pochodzących z ekologicznych upraw położonych w rejonach zgierskim i ozorkowskim.</p> </header> <main> <h4>Wybierz rodzaj wypieków:</h4> <formmethod="post"> <selectname="type"> </select> <buttontype="submit">Wybierz</button> </form> <table> <tr> <th>Rodzaj</th> <th>Nazwa</th> <th>Gramatura</th> <th>Cena</th> </tr> </table> </main> <footer> <p>AUTOR: Bartosz Bryniarski</p> <p>Data: 02.10.2026</p> </footer></body></html>
Podgląd strony po tym kroku (piekarnia.php)
Etap 3: Styl CSS
Kroki 23-32 · po tym etapie masz 31 z 40 kryteriów (pkt)
Krok 23: Plik styles.css: czcionka dla wszystkich
Kryteria:
R.4.1 Ustawione domyślne formatowanie wszystkich selektorów (*) krój czcionki: Verdana oraz dla body lub kontenera całej strony tło np. linear-gradient(Teal, AliceBlue), biały kolor czcionki, wyrównanie tekstu do środka, marginesy zewnętrzne (margin) lewy i prawy 20px
ok. 1 min
Polecenie z arkusza
Domyślne formatowanie wszystkich selektorów: krój czcionki Verdana.
„Wszystkie selektory” to selektor uniwersalny *.
styles.cssCSSnowy plik
* {font-family: Verdana;}
Podgląd strony po tym kroku (piekarnia.php)
Krok 24: Ciało strony: gradient i marginesy
Kryteria:
R.4.1 Ustawione domyślne formatowanie wszystkich selektorów (*) krój czcionki: Verdana oraz dla body lub kontenera całej strony tło np. linear-gradient(Teal, AliceBlue), biały kolor czcionki, wyrównanie tekstu do środka, marginesy zewnętrzne (margin) lewy i prawy 20px
ok. 2 min
Polecenie z arkusza
Dla ciała strony: tło jako gradient liniowy pionowy od koloru Teal do AliceBlue, biały kolor czcionki, wyrównanie tekstu do środka, jedynie marginesy zewnętrzne lewy i prawy 20 px.
linear-gradient(Teal, AliceBlue) bez kierunku biegnie z góry na dół, czyli pionowo. Gradient to obraz, więc we właściwości background, nie background-color. „Jedynie lewy i prawy” - margin: 0 20px: góra i dół 0, boki 20 px.
R.4.4 Ustawione cechy obrazu: blokowy sposób wyświetlania, stałe położenie na stronie z odstępem od góry 70px, np.: display: block; position: fixed; (lub absolute; ) top: 70px; dopuszcza się też margin-top: 70px;
R.4.5 Obraz jest pod spodem innych elementów strony np. z-index = -1
R.4.6 Ustawiona szerokość 100% dla obrazu i 70% dla tabeli
ok. 3 min
Polecenie z arkusza
Dla obrazu: szerokość 100%, blokowy sposób wyświetlania, stałe położenie na stronie z odstępem od góry 70 px. Obraz jest zawsze pod spodem treści strony.
display: block - obraz jako blok, a nie element w linii tekstu,
position: fixed i top: 70px - „stałe położenie”: obraz jest przypięty do okna 70 px od góry i nie przewija się razem ze stroną,
z-index: -1 - kolejność warstw: ujemna wartość stawia obraz pod blokami strony, więc nagłówek i blok główny go zakrywają (R.4.5).
Element z position: fixed wypada z normalnego układu - bloki strony zachowują się tak, jakby obrazu nie było, i zaczynają się od góry.
Typowe błędy
Bez z-index: -1 obraz przykrywa nagłówek. Selektor obrazu musi być img - przy klasie albo identyfikatorze sprawdź, czy pasuje do znacznika w HTML.
R.4.3 Ustawiony biały kolor czcionki dla odnośnika oraz cień zewnętrzny dla selektora h1: np. text-shadow: 2px 2px 5px black
R.4.7 Ustawiony rozmiar czcionki 130% dla odnośnika
R.4.8 Ustawione marginesy wewnętrzne (padding) 30px dla odnośnika, bloku głównego i stopki, 10px dla bloku nagłówkowego oraz margines zewnętrzny górny 100px dla bloku nagłówkowego i auto dla tabeli
Krok 27: Blok nagłówkowy: półprzezroczyste tło i zaokrąglone górne rogi
Kryteria: , ,
R.4.2 Ustawiony kolor tła RGBA(160, 82, 45, 0.6) dla bloku nagłówkowego (poprawnie również gdy zdefiniowano opacity: 0.6 ), SandyBrown dla bloku głównego, Sienna dla stopki i dla selektora table
R.4.8 Ustawione marginesy wewnętrzne (padding) 30px dla odnośnika, bloku głównego i stopki, 10px dla bloku nagłówkowego oraz margines zewnętrzny górny 100px dla bloku nagłówkowego i auto dla tabeli
R.4.9 Ustawione zaokrąglenie górnych rogów bloku nagłówkowego np. border-radius: 15px 15px 0 0; oraz dolnych rogów bloku stopki, np. border-radius: 0 0 15px 15px;
ok. 3 min
Polecenie z arkusza
Dla bloku nagłówkowego: kolor tła RGB 160, 82, 45 z przezroczystością 0.6, marginesy wewnętrzne 10 px, jedynie margines zewnętrzny górny 100 px, jedynie górne rogi zaokrąglone o 15 px.
rgba(160, 82, 45, 0.6) - kolor RGB z czwartą wartością: krycie 0.6, więc przez tło prześwituje obraz wypieków. opacity: 0.6 też przechodzi w kluczu, ale robi przezroczystym cały blok razem z tekstem,
margin-top: 100px - tylko górny margines; odsłania wypieki nad nagłówkiem,
border-radius: 15px 15px 0 0 - cztery wartości zgodnie z ruchem wskazówek zegara od lewego górnego rogu: górne dwa zaokrąglone, dolne proste.
R.4.2 Ustawiony kolor tła RGBA(160, 82, 45, 0.6) dla bloku nagłówkowego (poprawnie również gdy zdefiniowano opacity: 0.6 ), SandyBrown dla bloku głównego, Sienna dla stopki i dla selektora table
R.4.8 Ustawione marginesy wewnętrzne (padding) 30px dla odnośnika, bloku głównego i stopki, 10px dla bloku nagłówkowego oraz margines zewnętrzny górny 100px dla bloku nagłówkowego i auto dla tabeli
ok. 1 min
Polecenie z arkusza
Dla bloku głównego: kolor tła SandyBrown, marginesy wewnętrzne 30 px.
R.4.2 Ustawiony kolor tła RGBA(160, 82, 45, 0.6) dla bloku nagłówkowego (poprawnie również gdy zdefiniowano opacity: 0.6 ), SandyBrown dla bloku głównego, Sienna dla stopki i dla selektora table
R.4.8 Ustawione marginesy wewnętrzne (padding) 30px dla odnośnika, bloku głównego i stopki, 10px dla bloku nagłówkowego oraz margines zewnętrzny górny 100px dla bloku nagłówkowego i auto dla tabeli
R.4.9 Ustawione zaokrąglenie górnych rogów bloku nagłówkowego np. border-radius: 15px 15px 0 0; oraz dolnych rogów bloku stopki, np. border-radius: 0 0 15px 15px;
ok. 1 min
Polecenie z arkusza
Dla bloku stopki: kolor tła Sienna, marginesy wewnętrzne 30 px, jedynie dolne rogi zaokrąglone o 15 px.
border-radius: 0 0 15px 15px - górne rogi proste, dolne (prawy dolny i lewy dolny) zaokrąglone. Nagłówek i stopka razem tworzą jedną kartę z zaokrąglonymi rogami.
R.4.2 Ustawiony kolor tła RGBA(160, 82, 45, 0.6) dla bloku nagłówkowego (poprawnie również gdy zdefiniowano opacity: 0.6 ), SandyBrown dla bloku głównego, Sienna dla stopki i dla selektora table
R.4.6 Ustawiona szerokość 100% dla obrazu i 70% dla tabeli
R.4.8 Ustawione marginesy wewnętrzne (padding) 30px dla odnośnika, bloku głównego i stopki, 10px dla bloku nagłówkowego oraz margines zewnętrzny górny 100px dla bloku nagłówkowego i auto dla tabeli
ok. 1 min
Polecenie z arkusza
Dla selektora tabeli: marginesy zewnętrzne automatycznie wyliczane przez przeglądarkę, szerokość 70%, kolor tła Sienna.
margin: auto wyśrodkowuje tabelę w bloku głównym. Selektor znacznika table, jak wymaga arkusz.
R.4.10 Ustawione dla tabeli i komórek tabeli obramowanie linią ciągłą o grubości 1px i kolorze SandyBrown, dla tabeli obramowanie połączone (border-collapse: collapse)
ok. 1 min
Polecenie z arkusza
Wspólne dla selektora tabeli i komórek tabeli: obramowanie linią ciągłą o grubości 1 px i kolorze SandyBrown, obramowanie połączone.
border-collapse: collapse łączy sąsiednie ramki komórek w jedną linię. Ramka w kolorze tła bloku głównego wygląda jak jasne odstępy między komórkami.
Kroki 33-37 · po tym etapie masz 40 z 40 kryteriów (pkt)
Krok 33: Połączenie w liście, zamknięcie w tabeli
Kryteria: , ,
R.5.1 Skrypt jest napisany w języku PHP i zawiera przynajmniej jedną instrukcję zgodną z treścią zadania
R.5.2 Skrypt realizuje połączenie z serwerem bazy danych i wybór bazy piekarnia
R.5.3 Ostatnią operacją na bazie jest jej zamknięcie
ok. 3 min
Polecenie z arkusza
Łączą się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie piekarnia. Na końcu jest zamykane połączenie z serwerem.
Skrypt 1 stoi wewnątrz<select>, bo wypisuje elementy listy, a Skrypt 2 - w tabeli, pod wierszem nagłówkowym. Połączenie otwierasz w pierwszym bloku (Skrypt 1 jest wyżej na stronie, więc wykona się pierwszy), a zamknięcie mysqli_close stawiasz w drugim - to będzie ostatnia operacja na bazie (R.5.3). Zmienna $connection z pierwszego bloku jest dostępna w drugim - to ten sam plik PHP.
piekarnia.phpPHPzmienione: 6 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>PIEKARNIA</title> <linkrel="stylesheet"href="styles.css"></head><body> <imgsrc="wypieki.png"alt="Produkty naszej piekarni"> <nav> <ahref="kw1.png">KWERENDA1</a> <ahref="kw2.png">KWERENDA2</a> <ahref="kw3.png">KWERENDA3</a> <ahref="kw4.png">KWERENDA4</a> </nav> <header> <h1>WITAMY</h1> <h4>NA STRONIE PIEKARNI</h4> <p>Od 31 lat oferujemy najwyższej jakości pieczywo. Naturalnie świeże, naturalnie smaczne. Pieczemy wyłącznie wypieki na naturalnym zakwasie bez polepszaczy i zagęstników. Korzystamy wyłącznie z najlepszych ziaren pochodzących z ekologicznych upraw położonych w rejonach zgierskim i ozorkowskim.</p> </header> <main> <h4>Wybierz rodzaj wypieków:</h4> <formmethod="post"> <selectname="type"><?php$connection = mysqli_connect("localhost", "root", "", "piekarnia");?> </select> <buttontype="submit">Wybierz</button> </form> <table> <tr> <th>Rodzaj</th> <th>Nazwa</th> <th>Gramatura</th> <th>Cena</th> </tr><?php mysqli_close($connection);?> </table> </main> <footer> <p>AUTOR: Bartosz Bryniarski</p> <p>Data: 02.10.2026</p> </footer></body></html>
Podgląd strony po tym kroku (piekarnia.php)
Krok 34: Skrypt 1: wysłanie zapytania 2
Kryteria:
R.5.4 Skrypt 1 zawiera instrukcję wysyłającą do bazy danych zapytanie 2 lub skrypt 2 zawiera instrukcję wysyłającą do bazy danych zmodyfikowane zapytanie 1 w ten sposób, że wartość pola Rodzaj w warunku jest pobrana z formularza
ok. 2 min
Polecenie z arkusza
Skrypt 1: Wysyła do bazy danych zapytanie 2.
Zapytanie 2 w zmiennej $query i mysqli_query - wynik trafia do $result. Lista jest jeszcze pusta: wiersze trzeba pobrać i wypisać.
piekarnia.phpPHPzmienione: 2 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>PIEKARNIA</title> <linkrel="stylesheet"href="styles.css"></head><body> <imgsrc="wypieki.png"alt="Produkty naszej piekarni"> <nav> <ahref="kw1.png">KWERENDA1</a> <ahref="kw2.png">KWERENDA2</a> <ahref="kw3.png">KWERENDA3</a> <ahref="kw4.png">KWERENDA4</a> </nav> <header> <h1>WITAMY</h1> <h4>NA STRONIE PIEKARNI</h4> <p>Od 31 lat oferujemy najwyższej jakości pieczywo. Naturalnie świeże, naturalnie smaczne. Pieczemy wyłącznie wypieki na naturalnym zakwasie bez polepszaczy i zagęstników. Korzystamy wyłącznie z najlepszych ziaren pochodzących z ekologicznych upraw położonych w rejonach zgierskim i ozorkowskim.</p> </header> <main> <h4>Wybierz rodzaj wypieków:</h4> <formmethod="post"> <selectname="type"><?php$connection = mysqli_connect("localhost", "root", "", "piekarnia");$query = "SELECT DISTINCT Rodzaj FROM wyroby ORDER BY Rodzaj DESC;";$result = mysqli_query($connection, $query);?> </select> <buttontype="submit">Wybierz</button> </form> <table> <tr> <th>Rodzaj</th> <th>Nazwa</th> <th>Gramatura</th> <th>Cena</th> </tr><?php mysqli_close($connection);?> </table> </main> <footer> <p>AUTOR: Bartosz Bryniarski</p> <p>Data: 02.10.2026</p> </footer></body></html>
R.5.5 Skrypt 1 wyświetla zwrócone zapytaniem wiersze w kolejnych elementach listy rozwijanej
R.5.6 Działanie skryptu 1 oraz skryptu 2 jest uniwersalne dla dowolnej liczby zwróconych rekordów i jest zrealizowane z wykorzystaniem pętli
ok. 3 min
Polecenie z arkusza
Dane zwrócone zapytaniem wyświetla w kolejnych elementach listy rozwijanej.
Pętla while z mysqli_fetch_row - dla każdego z 11 rodzajów jeden <option>. Bez atrybutu value przeglądarka wyśle w formularzu sam tekst opcji, czyli nazwę rodzaju - dokładnie to, czego potrzebuje Skrypt 2. Pętla działa dla dowolnej liczby rodzajów (R.5.6). Podgląd: lista rozwijana z rodzajami, od „WYROBY CUKIERNICZE I CIASTKARSKIE”.
piekarnia.phpPHPzmienione: 3 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>PIEKARNIA</title> <linkrel="stylesheet"href="styles.css"></head><body> <imgsrc="wypieki.png"alt="Produkty naszej piekarni"> <nav> <ahref="kw1.png">KWERENDA1</a> <ahref="kw2.png">KWERENDA2</a> <ahref="kw3.png">KWERENDA3</a> <ahref="kw4.png">KWERENDA4</a> </nav> <header> <h1>WITAMY</h1> <h4>NA STRONIE PIEKARNI</h4> <p>Od 31 lat oferujemy najwyższej jakości pieczywo. Naturalnie świeże, naturalnie smaczne. Pieczemy wyłącznie wypieki na naturalnym zakwasie bez polepszaczy i zagęstników. Korzystamy wyłącznie z najlepszych ziaren pochodzących z ekologicznych upraw położonych w rejonach zgierskim i ozorkowskim.</p> </header> <main> <h4>Wybierz rodzaj wypieków:</h4> <formmethod="post"> <selectname="type"><?php$connection = mysqli_connect("localhost", "root", "", "piekarnia");$query = "SELECT DISTINCT Rodzaj FROM wyroby ORDER BY Rodzaj DESC;";$result = mysqli_query($connection, $query);while ($row = mysqli_fetch_row($result)) {echo"<option>$row[0]</option>"; }?> </select> <buttontype="submit">Wybierz</button> </form> <table> <tr> <th>Rodzaj</th> <th>Nazwa</th> <th>Gramatura</th> <th>Cena</th> </tr><?php mysqli_close($connection);?> </table> </main> <footer> <p>AUTOR: Bartosz Bryniarski</p> <p>Data: 02.10.2026</p> </footer></body></html>
Podgląd strony po tym kroku (piekarnia.php)
Krok 36: Skrypt 2: zapytanie 1 z rodzajem z formularza
Kryteria: ,
R.5.4 Skrypt 1 zawiera instrukcję wysyłającą do bazy danych zapytanie 2 lub skrypt 2 zawiera instrukcję wysyłającą do bazy danych zmodyfikowane zapytanie 1 w ten sposób, że wartość pola Rodzaj w warunku jest pobrana z formularza
R.5.8 Skrypt 2 jest zabezpieczony na wypadek braku danych wysyłanych z formularza
ok. 4 min
Polecenie z arkusza
Skrypt 2: Wysyła do bazy danych zapytanie 1 zmodyfikowane w ten sposób, że wartość pola Rodzaj w warunku jest pobrana z formularza. W stanie początkowym, gdy nie wybrano opcji listy rozwijanej, w tabeli nie są wyświetlane wiersze z danymi.
!empty($_POST["type"]) - przy pierwszym wejściu na stronę formularz nie był wysłany, $_POST["type"] nie istnieje i warunek jest fałszywy: tabela zostaje z samym nagłówkiem (R.5.8),
po wysłaniu wybrany rodzaj trafia do zmiennej $type i zastępuje „INNE” w zapytaniu 1. Wartość stoi w apostrofach '$type', bo to napis; całe zapytanie jest w cudzysłowie, więc PHP wstawi w nie wartość zmiennej,
mysqli_close stoi pod blokiem if, poza nim - połączenie zamykasz zawsze.
Podgląd: stan po wysłaniu formularza z „PIECZYWO MIESZANE” - zapytanie już poszło, ale wyniku jeszcze nie wypisujesz.
piekarnia.phpPHPzmienione: 5 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>PIEKARNIA</title> <linkrel="stylesheet"href="styles.css"></head><body> <imgsrc="wypieki.png"alt="Produkty naszej piekarni"> <nav> <ahref="kw1.png">KWERENDA1</a> <ahref="kw2.png">KWERENDA2</a> <ahref="kw3.png">KWERENDA3</a> <ahref="kw4.png">KWERENDA4</a> </nav> <header> <h1>WITAMY</h1> <h4>NA STRONIE PIEKARNI</h4> <p>Od 31 lat oferujemy najwyższej jakości pieczywo. Naturalnie świeże, naturalnie smaczne. Pieczemy wyłącznie wypieki na naturalnym zakwasie bez polepszaczy i zagęstników. Korzystamy wyłącznie z najlepszych ziaren pochodzących z ekologicznych upraw położonych w rejonach zgierskim i ozorkowskim.</p> </header> <main> <h4>Wybierz rodzaj wypieków:</h4> <formmethod="post"> <selectname="type"><?php$connection = mysqli_connect("localhost", "root", "", "piekarnia");$query = "SELECT DISTINCT Rodzaj FROM wyroby ORDER BY Rodzaj DESC;";$result = mysqli_query($connection, $query);while ($row = mysqli_fetch_row($result)) {echo"<option>$row[0]</option>"; }?> </select> <buttontype="submit">Wybierz</button> </form> <table> <tr> <th>Rodzaj</th> <th>Nazwa</th> <th>Gramatura</th> <th>Cena</th> </tr><?phpif (!empty($_POST["type"])) {$type = $_POST["type"];$query = "SELECT Rodzaj, Nazwa, Gramatura, Cena FROM wyroby WHERE Rodzaj = '$type';";$result = mysqli_query($connection, $query); } mysqli_close($connection);?> </table> </main> <footer> <p>AUTOR: Bartosz Bryniarski</p> <p>Data: 02.10.2026</p> </footer></body></html>
R.5.6 Działanie skryptu 1 oraz skryptu 2 jest uniwersalne dla dowolnej liczby zwróconych rekordów i jest zrealizowane z wykorzystaniem pętli
R.5.7 Skrypt 2 wyświetla zwrócone zapytaniem rekordy w kolejnych wierszach tabeli, w przeznaczonych do tego komórkach
R.5.9 W skryptach zastosowana przynajmniej jedna zmienna lub funkcja oraz nazwy wszystkich funkcji i zmiennych są w języku polskim lub angielskim i odzwierciedlają cel zastosowania
ok. 3 min
Polecenie z arkusza
Zwrócone zapytaniem wiersze wyświetla w kolejnych wierszach tabeli, w przeznaczonych do tego komórkach.
Dla każdego wyrobu wiersz <tr> z czterema <td> w kolejności kolumn zapytania: rodzaj, nazwa, gramatura, cena. Podgląd: 7 wyrobów z rodzaju PIECZYWO MIESZANE - jak na ilustracji 2. Lista po wysłaniu wraca do pierwszej opcji, bo strona ładuje się od nowa (ilustracja pokazuje to samo).
piekarnia.phpPHPzmienione: 3 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>PIEKARNIA</title> <linkrel="stylesheet"href="styles.css"></head><body> <imgsrc="wypieki.png"alt="Produkty naszej piekarni"> <nav> <ahref="kw1.png">KWERENDA1</a> <ahref="kw2.png">KWERENDA2</a> <ahref="kw3.png">KWERENDA3</a> <ahref="kw4.png">KWERENDA4</a> </nav> <header> <h1>WITAMY</h1> <h4>NA STRONIE PIEKARNI</h4> <p>Od 31 lat oferujemy najwyższej jakości pieczywo. Naturalnie świeże, naturalnie smaczne. Pieczemy wyłącznie wypieki na naturalnym zakwasie bez polepszaczy i zagęstników. Korzystamy wyłącznie z najlepszych ziaren pochodzących z ekologicznych upraw położonych w rejonach zgierskim i ozorkowskim.</p> </header> <main> <h4>Wybierz rodzaj wypieków:</h4> <formmethod="post"> <selectname="type"><?php$connection = mysqli_connect("localhost", "root", "", "piekarnia");$query = "SELECT DISTINCT Rodzaj FROM wyroby ORDER BY Rodzaj DESC;";$result = mysqli_query($connection, $query);while ($row = mysqli_fetch_row($result)) {echo"<option>$row[0]</option>"; }?> </select> <buttontype="submit">Wybierz</button> </form> <table> <tr> <th>Rodzaj</th> <th>Nazwa</th> <th>Gramatura</th> <th>Cena</th> </tr><?phpif (!empty($_POST["type"])) {$type = $_POST["type"];$query = "SELECT Rodzaj, Nazwa, Gramatura, Cena FROM wyroby WHERE Rodzaj = '$type';";$result = mysqli_query($connection, $query);while ($row = mysqli_fetch_row($result)) {echo"<tr><td>$row[0]</td><td>$row[1]</td><td>$row[2]</td><td>$row[3]</td></tr>"; } } mysqli_close($connection);?> </table> </main> <footer> <p>AUTOR: Bartosz Bryniarski</p> <p>Data: 02.10.2026</p> </footer></body></html>
Podgląd strony po tym kroku (piekarnia.php)
Etap 5: Dobre praktyki (poza kluczem)
Kroki 38-39 · po tym etapie masz 40 z 40 kryteriów (pkt)
Krok 38: SQL injection: luka pokazana i zamknięta
ok. 6 min
Polecenie z arkusza
Skrypt 2: Wysyła do bazy danych zapytanie 1 zmodyfikowane w ten sposób, że wartość pola Rodzaj w warunku jest pobrana z formularza.
Lista rozwijana daje złudzenie, że użytkownik może wybrać tylko jeden z 11 rodzajów. To nieprawda - formularz da się wysłać z dowolną wartością (narzędzia programisty w przeglądarce, curl). Sprawdzone na prawdziwym uruchomieniu: wartość x' OR '1'='1 zamienia warunek w WHERE Rodzaj = 'x' OR '1'='1', który jest prawdziwy dla każdego wiersza - tabela pokazała wszystkie 93 wyroby. Tak samo da się wyciągać dane z innych tabel.
Naprawa: zapytanie przygotowane. Znak ? to miejsce na wartość, mysqli_stmt_bind_param z typem "s" (napis) przekazuje ją osobno - baza nigdy nie potraktuje jej jak kodu SQL. Po zmianie ta sama próba zwraca 0 wierszy, a zwykły wybór z listy działa bez zmian. Stare linie zostają w komentarzu do porównania.
Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
piekarnia.phpPHPzmienione: 6 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>PIEKARNIA</title> <linkrel="stylesheet"href="styles.css"></head><body> <imgsrc="wypieki.png"alt="Produkty naszej piekarni"> <nav> <ahref="kw1.png">KWERENDA1</a> <ahref="kw2.png">KWERENDA2</a> <ahref="kw3.png">KWERENDA3</a> <ahref="kw4.png">KWERENDA4</a> </nav> <header> <h1>WITAMY</h1> <h4>NA STRONIE PIEKARNI</h4> <p>Od 31 lat oferujemy najwyższej jakości pieczywo. Naturalnie świeże, naturalnie smaczne. Pieczemy wyłącznie wypieki na naturalnym zakwasie bez polepszaczy i zagęstników. Korzystamy wyłącznie z najlepszych ziaren pochodzących z ekologicznych upraw położonych w rejonach zgierskim i ozorkowskim.</p> </header> <main> <h4>Wybierz rodzaj wypieków:</h4> <formmethod="post"> <selectname="type"><?php$connection = mysqli_connect("localhost", "root", "", "piekarnia");$query = "SELECT DISTINCT Rodzaj FROM wyroby ORDER BY Rodzaj DESC;";$result = mysqli_query($connection, $query);while ($row = mysqli_fetch_row($result)) {echo"<option>$row[0]</option>"; }?> </select> <buttontype="submit">Wybierz</button> </form> <table> <tr> <th>Rodzaj</th> <th>Nazwa</th> <th>Gramatura</th> <th>Cena</th> </tr><?phpif (!empty($_POST["type"])) {$type = $_POST["type"];// $query = "SELECT Rodzaj, Nazwa, Gramatura, Cena FROM wyroby WHERE Rodzaj = '$type';";// $result = mysqli_query($connection, $query);$statement = mysqli_prepare($connection, "SELECT Rodzaj, Nazwa, Gramatura, Cena FROM wyroby WHERE Rodzaj = ?"); mysqli_stmt_bind_param($statement, "s", $type); mysqli_stmt_execute($statement);$result = mysqli_stmt_get_result($statement);while ($row = mysqli_fetch_row($result)) {echo"<tr><td>$row[0]</td><td>$row[1]</td><td>$row[2]</td><td>$row[3]</td></tr>"; } } mysqli_close($connection);?> </table> </main> <footer> <p>AUTOR: Bartosz Bryniarski</p> <p>Data: 02.10.2026</p> </footer></body></html>
Krok 39: Zapamiętany wybór i bezpieczne wypisywanie
ok. 4 min
Polecenie z arkusza
Dane zwrócone zapytaniem wyświetla w kolejnych elementach listy rozwijanej.
Dwie drobne poprawki:
zapamiętany wybór - po wysłaniu lista wracała do pierwszej opcji i nie było widać, którego rodzaju dotyczy tabela. Opcja równa wysłanej wartości dostaje atrybut selected; ?? "" chroni przed ostrzeżeniem przy pierwszym wejściu, gdy $_POST["type"] nie istnieje,
htmlspecialchars przy wypisywaniu - nazwy wyrobów zawierają cudzysłowy (Chleb wieloziarnisty "Słońce"). W komórce tabeli to jeszcze nie szkodzi, ale ten sam tekst w atrybucie (value="...") urwałby go w połowie. Funkcja zamienia znaki specjalne HTML na encje i tekst zawsze wyświetla się dosłownie.
Podgląd: po wysłaniu „PIECZYWO MIESZANE” lista pokazuje wybrany rodzaj. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
piekarnia.phpPHPzmienione: 7 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>PIEKARNIA</title> <linkrel="stylesheet"href="styles.css"></head><body> <imgsrc="wypieki.png"alt="Produkty naszej piekarni"> <nav> <ahref="kw1.png">KWERENDA1</a> <ahref="kw2.png">KWERENDA2</a> <ahref="kw3.png">KWERENDA3</a> <ahref="kw4.png">KWERENDA4</a> </nav> <header> <h1>WITAMY</h1> <h4>NA STRONIE PIEKARNI</h4> <p>Od 31 lat oferujemy najwyższej jakości pieczywo. Naturalnie świeże, naturalnie smaczne. Pieczemy wyłącznie wypieki na naturalnym zakwasie bez polepszaczy i zagęstników. Korzystamy wyłącznie z najlepszych ziaren pochodzących z ekologicznych upraw położonych w rejonach zgierskim i ozorkowskim.</p> </header> <main> <h4>Wybierz rodzaj wypieków:</h4> <formmethod="post"> <selectname="type"><?php$connection = mysqli_connect("localhost", "root", "", "piekarnia");$query = "SELECT DISTINCT Rodzaj FROM wyroby ORDER BY Rodzaj DESC;";$result = mysqli_query($connection, $query);while ($row = mysqli_fetch_row($result)) {$selected = (($_POST["type"] ?? "") === $row[0]) ? " selected" : "";echo"<option$selected>" . htmlspecialchars($row[0]) . "</option>"; }?> </select> <buttontype="submit">Wybierz</button> </form> <table> <tr> <th>Rodzaj</th> <th>Nazwa</th> <th>Gramatura</th> <th>Cena</th> </tr><?phpif (!empty($_POST["type"])) {$type = $_POST["type"];// $query = "SELECT Rodzaj, Nazwa, Gramatura, Cena FROM wyroby WHERE Rodzaj = '$type';";// $result = mysqli_query($connection, $query);$statement = mysqli_prepare($connection, "SELECT Rodzaj, Nazwa, Gramatura, Cena FROM wyroby WHERE Rodzaj = ?"); mysqli_stmt_bind_param($statement, "s", $type); mysqli_stmt_execute($statement);$result = mysqli_stmt_get_result($statement);while ($row = mysqli_fetch_row($result)) {echo"<tr>";foreach ($rowas$value) {echo"<td>" . htmlspecialchars($value) . "</td>"; }echo"</tr>"; } } mysqli_close($connection);?> </table> </main> <footer> <p>AUTOR: Bartosz Bryniarski</p> <p>Data: 02.10.2026</p> </footer></body></html>
Podgląd strony po tym kroku (piekarnia.php)
Etap 6: Oddanie pracy
Krok 40 · po tym etapie masz 40 z 40 kryteriów (pkt)
Krok 40: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
Po zakończeniu pracy utwórz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowana była poprawność działania witryny. Umieść go w folderze z numerem zdającego.
W przeglądarka.txt wpisujesz nazwę przeglądarki.
W folderze: piekarnia.php, styles.css, kwerendy.txt, import.png, kw1.png - kw4.png (do nich prowadzą odnośniki w nawigacji), wypieki.png i przeglądarka.txt. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem zdającego.
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.