INF.03-02-26.01-SGStyczeń 2026 · 44 kroki · ok. 80 min · 40 kryteriów z klucza
Rozwiązanie krok po kroku: Portal Zdrowy bazarek (Wersja podstawowa)
Rozwiązanie buduje portal „Zdrowy bazarek”: baza bazar (towary z ceną i nazwą pliku zdjęcia, sklepy i tabela zamowienie, która łączy towar ze sklepem i liczbą kilogramów) i cztery zapytania - LIMIT, prosty SELECT, warunek na identyfikator i INSERT z kluczem nadawanym automatycznie - potem dwie grafiki (przezroczyste tło jabłka i przeskalowany szyld), strona index.php z paskiem owoców, blokiem bocznym i formularzem oraz trzy skrypty PHP: zdjęcia owoców wypisane z bazy, lista rozwijana towarów i zamówienie, które liczy wartość (cena × kilogramy) i zapisuje się w bazie.
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, funkcjami z tabeli 1 arkusza (mysqli_query, mysqli_fetch_row, isset), a na końcu zostają przerobione na wersję z prawdziwych projektów: walidacja liczby kilogramów, zapytania przygotowane, kwota w złotych z dwoma miejscami po przecinku i formularz, który pamięta wybrany towar.
To jest wersja podstawowa. W zakładce „Nowoczesny kod (grid, PDO)” jest drugi sposób rozwiązania tego samego arkusza: układ na siatce CSS, kolory w zmiennych i PHP na PDO z zapytaniami przygotowanymi od pierwszej linii - obie wersje są zgodne z kluczem.
Baza i zdjęcia pochodzą z prawdziwego archiwum pliki3-1 (załącznik do arkusza, hasło w treści zadania). Zrzuty wyników zapytań są odtworzone z tej bazy - na egzaminie robisz je sam, z całego ekranu. Podgląd strony od kroków z PHP to wynik prawdziwego uruchomienia kodu z danego kroku w PHP 8.2 na bazie z arkusza; od Skryptu 3 pokazuje zamówienie z ilustracji 5 (pietruszka, 30 kg).
Jak liczą się punkty. Klucz ma 40 kryteriów (R.1.1 - R.5.10), 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 bazar
ok. 2 min
Polecenie z arkusza
Utwórz bazę danych o nazwie bazar, z zestawem polskich znaków (np. utf8_polish_ci)
Rozpakuj pliki3-1.7z z pulpitu (hasło baz@rEk100% - małpa zamiast „a”, wielkie E i znak procentu na końcu) i załóż folder z numerem zdającego. W phpMyAdmin: Nowa, nazwa bazar (nie „bazarek” - tak nazywa się strona, a nie baza), porównywanie utf8_polish_ci.
Typowe błędy
Nazwa bazy musi brzmieć dokładnie bazar - skrypty łączą się z bazą po nazwie, więc literówka zabiera też punkty za skrypty (R.5.1).
Krok 2: Import tabel z pliku baza-nowa.sql
ok. 2 min
Polecenie z arkusza
Z rozpakowanego archiwum zaimportuj tabele z pliku baza-nowa.sql do utworzonej bazy
Zaznacz bazę bazar, potem Import → baza-nowa.sql → Wykonaj. Powstają trzy tabele z ilustracji 1: towar (nazwa, rodzaj, cena, nazwa pliku ze zdjęciem), sklep i zamowienie, która kluczami obcymi wskazuje towar i sklep i zapisuje liczbę kilogramów.
Krok 3: Zrzut ekranu import.png
Kryteria:
R.1.1 Wykonany import tabel do bazy danych bazar - plik import.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, wklejasz do edytora grafiki i zapisujesz jako import.png. W tym arkuszu wszystkie zrzuty - import i zapytania - idą do PNG.
Typowe błędy
Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).
Krok 4: Zapytanie 1: dziesięć pierwszych towarów
Kryteria: ,
R.1.2 W pliku kwerendy.txt zapisane co najmniej jedno zapytanie SQL, wynikające z treści zadania
R.1.3 Wykonane zapytanie 1 wybierające 10 pierwszych rekordów z tabeli towar , jedynie pola nazwa i plik. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT nazwa, plik FROM towar LIMIT 10; oraz na zrzucie widocznych jest dokładnie 10 wierszy z nazwami: gruszka, jabłko, banan, ananas, mango, winogrona, jagody, maliny, pomarańcza, cytryna
ok. 2 min
Polecenie z arkusza
Zapytanie 1: wybierające 10 pierwszych rekordów z tabeli towar, jedynie pola nazwa i plik
SELECT nazwa, plik - dwa pola,
FROM towar,
LIMIT 10 - zwraca tylko dziesięć pierwszych wierszy.
Wynik: gruszka, jabłko, banan, ananas, mango, winogrona, jagody, maliny, pomarańcza, cytryna - każdy z nazwą pliku zdjęcia, jak w kluczu. Z tego zapytania Skrypt 1 zrobi pasek zdjęć. Zapytania zapisujesz w kwerendy.txt, zrzut jako kw1.png.
kwerendy.txtTekstnowy plik
-- Zapytanie 1SELECT nazwa, plik FROM towar LIMIT 10;
Podgląd strony po tym kroku
Krok 5: Zapytanie 2: identyfikatory i nazwy towarów
Kryteria:
R.1.4 Wykonane zapytanie 2 wybierające jedynie id i nazwę towarów. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT id, nazwa FROM towar; oraz na zrzucie widoczne są wyniki działania zapytania (nie wszystkie rekordy będą widoczne, 39 lub 40 rekordów)
ok. 1 min
Polecenie z arkusza
Zapytanie 2: wybierające jedynie identyfikator i nazwę towarów
Dwa pola bez warunku: 39 wierszy (klucz: 39 lub 40). Na zrzucie nie zmieszczą się wszystkie - to w porządku, klucz o tym wie. Skrypt 2 zrobi z tego listę rozwijaną: identyfikator pójdzie do value, nazwa będzie widoczną treścią. Zrzut: kw2.png.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT nazwa, plik FROM towar LIMIT 10;-- Zapytanie 2SELECT id, nazwa FROM towar;
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: towar o identyfikatorze 1
Kryteria:
R.1.5 Wykonane zapytanie 3 wybierające jedynie rodzaj, nazwę i cenę towaru dla id = 1. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT rodzaj, nazwa, cena FROM towar WHERE id = 1; oraz na zrzucie widoczny jest dokładnie jeden rekord: owoc gruszka 5.00
ok. 1 min
Polecenie z arkusza
Zapytanie 3: wybierające jedynie rodzaj, nazwę i cenę towaru o identyfikatorze 1
Trzy pola i warunek na klucz główny - zawsze najwyżej jeden wiersz: owoc gruszka 5.00. Zrzut: kw3.png. W Skrypcie 3 w miejscu 1 stanie identyfikator wybrany w formularzu, a cena posłuży do policzenia wartości zamówienia.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT nazwa, plik FROM towar LIMIT 10;-- Zapytanie 2SELECT id, nazwa FROM towar;-- Zapytanie 3SELECT rodzaj, nazwa, cena FROM towar WHERE id = 1;
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: zamówienie 20 kg pomarańczy
Kryteria:
R.1.6 Wykonane zapytanie 4 wstawiające do tabeli zamowienie rekord o wartościach: towar o id 9, sklep o id 2, liczba kilogramów 20, klucz główny nadawany automatycznie. W pliku z kwerendami lub na zrzucie istnieje zapis np. INSERT INTO zamowienie(id_towar, id_sklep, liczba_kg) VALUES (9, 2, 20); (klucz główny pominięty lub NULL) oraz na zrzucie jest widoczny komunikat o poprawnie wykonanym zapytaniu lub tabela z dodanym rekordem
ok. 2 min
Polecenie z arkusza
Zapytanie 4: wstawiające do tabeli zamowienie rekord o wartościach: towar o identyfikatorze 9, sklep o identyfikatorze 2, liczba kilogramów 20, klucz główny nadawany automatycznie
Wymień w nawiasie tylko trzy kolumny, które wypełniasz - id pomiń i baza nada je sama (AUTO_INCREMENT). Nowe zamówienie dostało identyfikator 49: 20 kg pomarańczy (towar 9) dla sklepu „dino” (sklep 2). Zrzut z komunikatem albo z tabelą po wstawieniu: kw4.png.
Typowe błędy
Wpisanie klucza ręcznie (VALUES (49, 9, 2, 20)) przeczy wymaganiu „klucz główny nadawany automatycznie” - klucz pomijasz albo podajesz NULL.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT nazwa, plik FROM towar LIMIT 10;-- Zapytanie 2SELECT id, nazwa FROM towar;-- Zapytanie 3SELECT rodzaj, nazwa, cena FROM towar WHERE id = 1;-- Zapytanie 4INSERT INTO zamowienie (id_towar, id_sklep, liczba_kg) VALUES (9, 2, 20);
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 8-23 · po tym etapie masz 18 z 40 kryteriów (pkt)
Krok 8: Grafika jabłka z przezroczystym tłem
Kryteria:
R.2.1 Grafika jablko.png lub jabłko.png ma przezroczyste tło
ok. 4 min
Polecenie z arkusza
Dla grafiki jablko.png należy nadać tło przezroczyste i zapisać pod tą samą nazwą
Tło jabłka to jednolity kremowy kolor. W GIMP-ie: Warstwa → Przezroczystość → Dodaj kanał alfa, potem różdżka (zaznaczanie ciągłych obszarów) kliknięta w tło i Delete. Różdżka zaznacza tylko piksele połączone z miejscem kliknięcia, więc jabłko i liść zostają; delikatny cień pod owocem ma inny kolor, więc też zostaje. Eksport do PNG pod tą samą nazwą. Po lewej oryginał, po prawej wynik na szachownicy, która oznacza przezroczystość - przezroczystych jest 14907 z 22 500 pikseli.
Uwaga na nazwę: arkusz pisze jablko.png, ale w archiwum i w bazie (pole plik) jest jabłko.png z „ł”. Na egzaminie zapisujesz plik pod nazwą z archiwum - wtedy Skrypt 1 go znajdzie; klucz uznaje obie nazwy (R.2.1).
Typowe błędy
JPEG nie ma przezroczystości - eksport do .jpg zamieni przezroczyste tło na białe.
Podgląd strony po tym kroku
Krok 9: Grafika market.png: szerokość 300 px
Kryteria:
R.2.2 Grafika market.png przeskalowana z zachowaniem proporcji do szerokości dokładnie 300 px, odpowiadająca temu wysokość to 378 px ( ± 5 px)
ok. 3 min
Polecenie z arkusza
Grafikę market.png należy przeskalować z zachowaniem proporcji do szerokości 300 px
Oryginał ma 508 × 640 px. W GIMP-ie Obraz → Skaluj obraz, szerokość 300 px przy zamkniętym łańcuchu proporcji - wysokość wychodzi sama: 378 px (klucz: 378 ±5). Eksport pod tą samą nazwą, w PNG - szyld ma przezroczyste tło i ma je zachować.
Typowe błędy
Wpisanie samej szerokości przy otwartym łańcuchu zostawia wysokość 640 px - szyld jest zniekształcony i niezgodny z kluczem.
Podgląd strony po tym kroku
Krok 10: Plik index.php w HTML5
ok. 2 min
Polecenie z arkusza
Składa się ze strony o nazwie index.php. Zapisana w języku HTML5
Deklaracja <!DOCTYPE html> i szkielet strony. Rozszerzenie .php, bo dojdą skrypty; na egzaminie plik leży w htdocs XAMPP-a i otwierasz go przez http://localhost/....
R.2.5 W sekcji body zdefiniowany jest podział na bloki za pomocą semantycznych znaczników HTML5: header, nav, main->aside+section, footer (dopuszcza się zastosowanie bloków pomocniczych)
ok. 2 min
Polecenie z arkusza
Podział strony na bloki zrealizowany za pomocą semantycznych znaczników bloków języka HTML5 tak, aby po uruchomieniu w przeglądarce układ bloków na stronie był zgodny z ilustracją 3
Klucz wymaga wprost header, nav, main z aside i section w środku oraz footer (R.2.5). Blok boczny i sekcję postawisz obok siebie w CSS - w HTML-u wystarczy, że oba są wewnątrz <main>.
Zawartość bloku sekcji: Paragraf o treści: „Wybierz owoc lub warzywo i podaj jego wagę:”
Zwykły akapit <p> na początku sekcji.
index.phpPHPzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Zdrowy bazarek</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Zdrowy bazarek</h1> </header> <nav> </nav> <main> <aside> <imgsrc="market.png"alt="bazarek"> </aside> <section> <p>Wybierz owoc lub warzywo i podaj jego wagę:</p> </section> </main> <footer> </footer></body></html>
Podgląd strony po tym kroku (index.php)
Krok 19: Formularz wysyłany metodą POST
Kryteria: ,
R.2.8 W bloku sekcji umieszczony formularz
R.3.3 Formularz wysyła dane metodą POST do tego samego pliku (poprawne również bez atrybutu action)
ok. 1 min
Polecenie z arkusza
Formularz wysyłający dane do tego samego pliku metodą bezpieczną
method="post" - „metoda bezpieczna” w rozumieniu arkusza: dane jadą w treści żądania, a nie w adresie, więc nie zostają w historii przeglądarki ani w zakładkach. (W specyfikacji HTTP „bezpieczna” znaczy co innego - metodę, która niczego nie zmienia na serwerze, czyli GET - ale klucz R.3.3 rozstrzyga: POST.) Atrybut action pomijasz - formularz bez niego wysyła dane do bieżącego pliku (klucz: „poprawne również bez atrybutu action”).
Pole edycyjne przeznaczone do wpisywania jedynie liczb całkowitych
type="number" - przeglądarka przyjmie tylko liczbę. Domyślny krok pola liczbowego to 1 (step="1"), więc przy próbie wysłania 2,5 przeglądarka zgłosi błąd - pole przyjmuje tylko liczby całkowite, jak chce arkusz. name="weight" to klucz w $_POST.
R.2.6 W bloku nagłówkowym umieszczony <h1>: "Zdrowy bazarek", w bloku sekcji <p>, w stopce <p> z numerem zdającego
ok. 1 min
Polecenie z arkusza
Zawartość stopki: paragraf o treści: „Stronę opracował: ”, dalej wstawiony numer zdającego
Akapit w <footer>. Na egzaminie po dwukropku wpisujesz swój numer zdającego (PESEL) - tutaj stoi imię i nazwisko autora rozwiązania. Z tym krokiem są już elementy z kryterium R.2.6: <h1>, akapit w sekcji i akapit w stopce.
Dla bloku nawigacyjnego: kolor tła DarkKhaki, wysokość 150 px, w przypadku przepełnienia bloku pozostała jego zawartość jest ukryta (na ilustracji 2 jest 8 owoców – reszta nie zmieściła się w bloku i została ukryta)
Zdjęcia mają po 150 px wysokości, czyli tyle, ile blok - mieści się dokładnie jeden rząd. Owoce, które nie zmieszczą się w szerokości okna, przechodzą do drugiego rzędu, a overflow: hidden go ucina: na wąskim ekranie widać mniej owoców, na szerokim więcej (podpis ilustracji 2). auto dodałoby pasek przewijania, a tego arkusz nie chce.
R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z ilustracją 3 w arkuszu egzaminacyjnym (prawidłowo zastosowano właściwości CSS decydujące o układzie bloków na stronie, np. float i clear albo display flex albo grid albo position)
ok. 2 min
Polecenie z arkusza
Podział strony na bloki zrealizowany za pomocą semantycznych znaczników bloków języka HTML5 tak, aby po uruchomieniu w przeglądarce układ bloków na stronie był zgodny z ilustracją 3
Arkusz nie mówi, jak postawić blok boczny obok sekcji - wybierasz display: flex na <main>. Dzieci kontenera flex stają w rzędzie, a dwa razy 50% daje całą szerokość. Przy float trzeba by jeszcze dodać clear: both stopce; flex nie wypuszcza dzieci poza kontener, więc stopka sama zostaje pod spodem (R.3.1).
Typowe błędy
Bloki, które na siebie zachodzą (sprawdzane w inspektorze), zabierają punkt za układ, nawet gdy strona „na oko” wygląda dobrze.
R.4.9 styl jedynie dla obrazu w bloku bocznym: marginesy wewnętrzne - 2px, zewnętrzne - 10px, obramowanie 2px dotted ForestGreen, zaokrąglenie rogów 40px (dowolną metodą: id, klasa, potomek)
ok. 2 min
Polecenie z arkusza
Jedynie dla obrazu w bloku bocznym: marginesy wewnętrzne 2 px, zewnętrzne 10 px, obramowanie linią kropkową o szerokości 2 px i kolorze ForestGreen, zaokrąglenie rogów 40 px
„Jedynie dla obrazu w bloku bocznym” - samo img objęłoby też zdjęcia owoców. Selektor potomka aside img trafia tylko w obrazy wewnątrz <aside> (klucz dopuszcza też identyfikator albo klasę). dotted to linia z kropek.
Kroki 31-41 · po tym etapie masz 40 z 40 kryteriów (pkt)
Krok 31: Połączenie z bazą i zamknięcie na końcu
Kryteria:
R.5.1 Skrypt realizuje połączenie z serwerem bazy danych i wybór bazy bazar oraz ostatnią operacją na bazie jest jej zamknięcie
ok. 2 min
Polecenie z arkusza
Łączą się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie bazar. Po wykonaniu wszystkich operacji połączenie z bazą jest zamykane
Pierwszy skrypt na stronie stoi w bloku nawigacyjnym, więc tam otwierasz połączenie: mysqli_connect z czterema argumentami łączy się z serwerem i od razu wybiera bazę. Uchwyt w zmiennej $connection posłuży wszystkim trzem skryptom. Ostatni blok PHP, pod formularzem, na razie tylko zamyka połączenie - Skrypt 3 dopiszesz nad tą linią (R.5.1). Od tego kroku podgląd to wynik prawdziwego uruchomienia strony.
R.5.4 Skrypt 1 wyświetla obrazy dla każdego wiersza pobranego z bazy, źródłem jest pole plik, tekstem alternatywnym jest nazwa (obrazy mogą być ukryte za sprawą właściwości CSS overflow, zamiast obrazu z jabłkiem może się wyświetlać tekst alternatywny)
ok. 3 min
Polecenie z arkusza
Skrypt 1: dla każdego wiersza pobranego z bazy wyświetla obraz o pobranej z bazy nazwie pliku i tekście alternatywnym odpowiadającym nazwie owocu
mysqli_fetch_row oddaje kolejny wiersz jako tablicę w kolejności pól z SELECT: $row[0] - nazwa, $row[1] - plik. Plik idzie do src, nazwa do alt. Cudzysłowy atrybutów wewnątrz napisu PHP poprzedzasz ukośnikiem \". W podglądzie pasek owoców; na szerokim ekranie zmieści się więcej niż 8 z ilustracji 2, na wąskim mniej - nadmiar ucina overflow: hidden.
Skrypt 2 piszesz wewnątrz<select> - to, co wypisze, stanie się opcjami listy. Zmiennych $query i $result używasz ponownie: pasek owoców jest już wypisany.
Krok 35: Skrypt 2: opcje z identyfikatorem w value
Kryteria: ,
R.5.5 Skrypt 2 wypełnia listę rozwijaną z danymi pobranymi z bazy, atrybut value to id, wyświetlana wartość opcji to nazwa towaru
R.2.9 Na stronie umieszczona lista rozwijana (w HTML lub skrypcie), zastosowane znaczniki < select> i <option> , pole edycyjne i przycisk "Zamów"
ok. 2 min
Polecenie z arkusza
Skrypt 2: dla każdego wiersza pobranego z bazy generuje opcję listy rozwijanej, gdzie w atrybucie value znajduje się zwrócone pole id, a w treści opcji znajduje się nazwa towaru
Widać nazwę, a formularz wyśle value, czyli identyfikator - zapytanie 3 szuka towaru po id. Rozwiń listę w podglądzie: 39 towarów, pierwsza gruszka, jak na ilustracji 4. Z opcjami lista spełnia kryterium R.2.9 (<select> i <option>, pole edycyjne i przycisk „Zamów”).
Skrypt 3, wykonywany tylko wtedy, gdy wysłano dane z formularza
Przy zwykłym wejściu na stronę tablica $_POST jest pusta, po kliknięciu „Zamów” ma klucze product i weight. Warunek isset na jednym polu wystarczy. Zamknięcie połączenia stoi pod blokiem if, poza nim - wykona się zawsze, także bez wysłania formularza, i nadal jako ostatnia operacja na bazie.
R.5.6 Skrypt 3 stosuje tablicę $_POST dla danych wysłanych z formularza
ok. 2 min
Polecenie z arkusza
Pobiera wartości z formularza: id towaru i liczbę kilogramów
Obie wartości czekają w tablicy $_POST pod nazwami nadanymi polom (product, weight). Przepisz je do zmiennych o czytelnych nazwach. Podgląd pokazuje stronę po wybraniu pietruszki i wpisaniu 30 kg, jak na ilustracji 5 - na razie nic się nie zmienia, skrypt jeszcze niczego nie wypisuje.
Typowe błędy
Puste pole wagi kończy się w PHP 8 błędem krytycznym „Unsupported operand types: string * string” przy mnożeniu ceny przez wagę - strona urywa się w połowie (sprawdzone w PHP 8.2). Klucz tego nie sprawdza - zabezpieczenie jest w etapie „Dobre praktyki”.
Krok 38: Skrypt 3: zapytanie 3 dla wybranego towaru
Kryteria:
R.5.3 Skrypt zawiera instrukcję wysyłającą do bazy danych zmodyfikowane zapytanie 3: sprawdzane jest id przesłane formularzem lub zmodyfikowane zapytanie 4: wstawiany jest rekord z id towaru i liczbą kg przesłaną zapytaniem
ok. 2 min
Polecenie z arkusza
Wysyła do bazy danych zmodyfikowane zapytanie 3, tak że wybierany jest rekord o id wskazanym w formularzu
Zapytanie 3, w którym zamiast 1 stoi $productId. Warunek na klucz główny zwraca jeden wiersz, więc wystarczy jedno mysqli_fetch_row bez pętli: w $row masz rodzaj, nazwę i cenę.
R.5.7 Skrypt 3 oblicza wartość iloczynu ceny zwróconej zapytaniem oraz liczby kilogramów wysłanej z formularza
ok. 2 min
Polecenie z arkusza
Oblicza wartość na podstawie zwróconej zapytaniem ceny oraz liczby kilogramów wysłanej z formularza
Wartość to cena razy kilogramy. Cena przychodzi z bazy jako tekst „14.70”, a liczba kilogramów z formularza jako tekst „30” - operator * w PHP zamienia oba na liczby: 14,70 × 30 = 441.
R.5.8 Skrypt 3 wyświetla w paragrafie tekst: „<rodzaj> <nazwa> wartość: <wartość> zł”, gdzie w znakach <> umieszczono zwrócone zapytaniem pola i wyliczoną wartość
ok. 2 min
Polecenie z arkusza
Wypisuje w dodatkowym paragrafie pod formularzem tekst: „<rodzaj><nazwa> wartość: <wartość> zł”, gdzie w znakach <> umieszczono zwrócone zapytaniem pola i wyliczoną wartość
Blok PHP stoi pod formularzem, więc akapit pojawi się pod nim. Podgląd: „warzywo pietruszka wartość: 441 zł” - dokładnie jak na ilustracji 5. PHP wypisuje liczbę bez zbędnych zer, więc 441,0 staje się „441”.
R.5.9 Skrypt 3 wstawia do tabeli zamowienie rekord z danymi pobranymi z formularza (należy sprawdzić w phpMyAdmin)
R.5.10 W skryptach zastosowana przynajmniej jedna zmienna oraz nazwy wszystkich zmiennych są w języku polskim lub angielskim i odzwierciedlają cel zastosowania
ok. 3 min
Polecenie z arkusza
Wstawia do bazy rekord za pomocą zmodyfikowanego zapytania 4, w ten sposób, że w miejscu id towaru i liczby kilogramów są wpisywane odpowiednie wartości wysłane z formularza (id sklepu pozostaje bez zmian lub jest pomijane)
Zapytanie 4 z $productId i $weight w miejscu 9 i 20; sklep 2 zostaje. Sprawdzone, tak jak każe klucz, w bazie: po zamówieniu pietruszki w tabeli zamowienie przybył rekord 50 (towar 12, sklep 2, 30 kg). Wszystkie zmienne mają nazwy mówiące, co przechowują ($connection, $query, $result, $row, $productId, $weight, $value) - to kryterium R.5.10.
Kroki 42-43 · po tym etapie masz 40 z 40 kryteriów (pkt)
Krok 42: Zamówienie: walidacja wagi i zapytania przygotowane
ok. 4 min
Polecenie z arkusza
Skrypt 3: pobiera wartości z formularza, wysyła zmodyfikowane zapytanie 3, oblicza wartość, wypisuje ją w paragrafie i wstawia rekord zmodyfikowanym zapytaniem 4
Wersja z egzaminu sprawdzona dwoma „złośliwymi” wysłaniami. Puste pole wagi kończy stronę błędem PHP „Unsupported operand types: string * string” - w PHP 8 mnożenie ceny przez pusty tekst jest błędem, a nie zerem. Waga -5 przechodzi bez słowa: strona pisze „wartość: -73.5 zł”, a w tabeli zamowienie ląduje zamówienie na minus 5 kg (pole type="number" przyjmuje liczby ujemne). Poprawki: rzutowanie (int) i warunek > 0 dla obu wartości (inaczej komunikat zamiast zamówienia), zapytania przygotowane (mysqli_prepare + mysqli_stmt_bind_param), sprawdzenie, czy towar istnieje (identyfikator spoza bazy, np. 999 wysłany z pominięciem formularza, daje komunikat „Nie ma takiego towaru.” zamiast błędu klucza obcego), i kwota przez number_format - dwa miejsca po przecinku i polski przecinek: „441,00 zł”. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
index.phpPHPzmienione: 22 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Zdrowy bazarek</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Zdrowy bazarek</h1> </header> <nav><?php$connection = mysqli_connect("localhost", "root", "", "bazar");$query = "SELECT nazwa, plik FROM towar LIMIT 10;";$result = mysqli_query($connection, $query);while ($row = mysqli_fetch_row($result)) {echo"<img src=\"$row[1]\" alt=\"$row[0]\">"; }?> </nav> <main> <aside> <imgsrc="market.png"alt="bazarek"> </aside> <section> <p>Wybierz owoc lub warzywo i podaj jego wagę:</p> <formmethod="post"> <selectname="product"><?php$query = "SELECT id, nazwa FROM towar;";$result = mysqli_query($connection, $query);while ($row = mysqli_fetch_row($result)) {echo"<option value=\"$row[0]\">$row[1]</option>"; }?> </select> <inputtype="number"name="weight"> <buttontype="submit">Zamów</button> </form><?php$productId = (int) ($_POST["product"] ?? 0);$weight = (int) ($_POST["weight"] ?? 0);if ($productId > 0 && $weight > 0) {$statement = mysqli_prepare($connection, "SELECT rodzaj, nazwa, cena FROM towar WHERE id = ?"); mysqli_stmt_bind_param($statement, "i", $productId); mysqli_stmt_execute($statement);$product = mysqli_fetch_row(mysqli_stmt_get_result($statement));if ($product) {$value = $product[2] * $weight;echo"<p>" . htmlspecialchars($product[0] . "" . $product[1]) . " wartość: " . number_format($value, 2, ",", "") . " zł</p>";$statement = mysqli_prepare($connection, "INSERT INTO zamowienie (id_towar, id_sklep, liczba_kg) VALUES (?, 2, ?)"); mysqli_stmt_bind_param($statement, "ii", $productId, $weight); mysqli_stmt_execute($statement); } else {echo"<p>Nie ma takiego towaru.</p>"; } } elseif (isset($_POST["product"])) {echo"<p>Podaj liczbę kilogramów większą od zera.</p>"; } mysqli_close($connection);/* Wersja z egzaminu: if (isset($_POST["product"])) { $productId = $_POST["product"]; $weight = $_POST["weight"]; $query = "SELECT rodzaj, nazwa, cena FROM towar WHERE id = $productId;"; $result = mysqli_query($connection, $query); $row = mysqli_fetch_row($result); $value = $row[2] * $weight; echo "<p>$row[0] $row[1] wartość: $value zł</p>"; $query = "INSERT INTO zamowienie (id_towar, id_sklep, liczba_kg) VALUES ($productId, 2, $weight);"; mysqli_query($connection, $query); } */?> </section> </main> <footer> <p>Stronę opracował: Bartosz Bryniarski</p> </footer></body></html>
Podgląd strony po tym kroku (index.php)
Krok 43: Formularz pamięta wybrany towar, waga od 1 kg
ok. 3 min
Polecenie z arkusza
Lista rozwijana wypełniona skryptem 2. Pole edycyjne przeznaczone do wpisywania jedynie liczb całkowitych
Na ilustracji 5 po zamówieniu na liście nadal stoi „pietruszka”, a wersja z egzaminu po przeładowaniu wraca do gruszki. Skrypt 2 dopisuje teraz selected do opcji, której identyfikator przyszedł z formularza - w podglądzie po zamówieniu wybrana jest pietruszka. W polu wagi atrybuty min="1" i required zatrzymują puste i ujemne wartości już w przeglądarce; kontrola w PHP z poprzedniego kroku zostaje, bo przeglądarkę da się ominąć. Nazwy towarów wypisujesz przez htmlspecialchars. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
Krok 44 · po tym etapie masz 40 z 40 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 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. Nagraj płytę z rezultatami pracy.
W przeglądarka.txt wpisujesz nazwę przeglądarki, w której sprawdzasz stronę.
W folderze z numerem zdającego: import.png, index.php, jabłko.png, kw1.png - kw4.png, kwerendy.txt, market.png, przeglądarka.txt, styl.css oraz pozostałe zdjęcia owoców z archiwum (Skrypt 1 ich używa). 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.