Serwis używa plików cookies do analizy ruchu i poprawy działania. Szczegóły
E.14-01-23.06-SGCzerwiec 2023 · 42 kroki · ok. 78 min · 36 kryteriów z klucza
Rozwiązanie krok po kroku: Atlas zwierząt z wyborem gromady (Wersja podstawowa)
Atlas zwierząt: baza baza zaimportowana z pliku baza2.sql, cztery zapytania (ryby z tabeli Zwierzeta, złączenie z tabelą Gromady, liczba ssaków i nowe konto użytkownika CREATE USER), strona index.php z banerem, formularzem wyboru gromady i trzema blokami głównymi, style w styl3.css oraz dwa skrypty PHP: pierwszy wypisuje zwierzęta gromady wybranej w polu numerycznym, drugi - wszystkie zwierzęta z nazwą gromady.
To arkusz E.14 z sesji czerwiec 2023 - kwalifikacji formuły 2012, którą zastąpiła INF.03. To samo zadanie wróciło w styczniu 2021 oraz w czerwcu 2024 i 2025 (każde wydanie ma w serwisie własny arkusz i własne rozwiązanie, bo różnią się brzmieniem arkusza albo klucza). Kroki idą zdanie po zdaniu za treścią arkusza - przy każdym jest polecenie z arkusza, a kod pokazuje dokładnie te linie, które je spełniają. Skrypt jest najpierw napisany najprościej, funkcjami mysqli z tabeli 1 arkusza, a na końcu sprawdzony na prawdziwym wstrzyknięciu SQL i zabezpieczony.
To jest wersja podstawowa. W zakładce „Nowoczesny kod (flex, PDO)” jest drugi sposób rozwiązania tego samego arkusza: semantyczne bloki z flex, zmienne CSS, etykieta <label> i PDO z zapytaniem przygotowanym - obie wersje są zgodne z kluczem.
Baza i zdjęcie pochodzą z oryginalnego archiwum CKE z sesji styczeń 2019, w której zadanie pojawiło się po raz pierwszy (załącznik do pobrania na stronie arkusza): otwiera się hasłem z arkusza i zawiera oba pliki, o których arkusz mówi. Arkusz nazywa archiwum materialy-03.zip, zawartość jest ta sama. Zapytania i zrzuty są policzone na MariaDB 10.4 - tej samej, która jest w XAMPP. Podgląd od kroków z PHP to wynik prawdziwego uruchomienia kodu w PHP 8.2.
Jak liczą się punkty. Klucz ma 36 kryteriów (R.1.1 - R.5.8), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 27 punktów - można stracić 9 kryteriów i nadal zdać. Przy każdym kroku jest napisane, które kryteria spełnia; egzaminator ocenia spełnienie kryteriów z klucza, nie zgodność z tym kodem.
Suwak i strzałki obok niego - albo ←→ na klawiaturze - przechodzą krok po kroku; wyjaśnienie, pliki i podgląd zmieniają się razem z krokiem.
Lista „Etap” przenosi od razu do wybranego etapu.
„Rozwiązuję samodzielnie” chowa rozwiązanie kroku - najpierw własna próba, potem odsłonięcie.
„Tryb prezentacji” pokazuje same kroki, bez menu strony - na rzutnik.
Etap 1: Baza danych
Kroki 1-7 · po tym etapie masz 6 z 36 kryteriów (pkt)
Krok 1: Folder zdającego i archiwum z materiałami
ok. 2 min
Polecenie z arkusza
Na pulpicie znajdziesz archiwum ZIP o nazwie materialy-03.zip zabezpieczone hasłem: G@tuneK Archiwum należy rozpakować. Na pulpicie konta Egzamin utwórz folder. Jako nazwy folderu użyj swojego numeru PESEL. Rozpakowane pliki umieść w tym folderze. Po skończonej pracy wyniki zapisz 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 materialy-03.zip rozpakowujesz programem 7-Zip do tego folderu, podając hasło G@tuneK (wielkość liter ma znaczenie, @ zamiast litery „a”). W środku są dwa pliki: baza2.sql (tabele do importu) i zwierzeta.jpg (zdjęcie do bloku lewego).
Do tego folderu trafia wszystko, co powstanie: zrzuty, kwerendy.txt, index.php i styl3.css. Na stronie arkusza w serwisie archiwum jest w wersji materialy3.zip z pierwszego wydania zadania - hasło i pliki są te same.
Typowe błędy
Pliki zapisane poza folderem zdającego (np. tylko w htdocs) nie trafią na płytę - a ocenia się wyłącznie to, co jest na płycie.
Krok 2: XAMPP i pusta baza o nazwie baza
ok. 2 min
Polecenie z arkusza
Uruchom usługi MySQL i Apache za pomocą XAMPP Control Panel. Za pomocą narzędzia phpMyAdmin wykonaj podane operacje na bazie danych: Utwórz nową bazę danych o nazwie baza
W XAMPP Control Panel klikasz Start przy Apache i MySQL, potem w przeglądarce otwierasz http://localhost/phpmyadmin. Nowa w lewym panelu, nazwa baza (tak dosłownie brzmi nazwa bazy w arkuszu), porównywanie np. utf8mb4_polish_ci, Utwórz. Baza jest na razie pusta - tabele przyjdą z importu.
Typowe błędy
Nazwa bazy musi brzmieć dokładnie baza - z nią połączy się skrypt PHP (R.5.2), a import do innej bazy nie daje R.1.1.
Krok 3: Import pliku baza2.sql i zrzut import.png
Kryteria:
R.1.1 Wykonano import tabel do bazy danych baza , czynność udokumentowano plikiem o nazwie import w formacie PNG. Zrzut zawiera cały obszar ekranu monitora z widocznym paskiem zadań
ok. 3 min
Polecenie z arkusza
Do bazy zaimportuj tabele z pliku baza2.sql z rozpakowanego archiwum Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w folderze z numerem zdającego, w formacie PNG i nazwij 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
Zaznacz bazę baza w lewym panelu, karta Import, Wybierz plik → baza2.sql, Wykonaj. Plik tworzy 12 tabel - poza trzema z obrazu 1 (zwierzeta, gromady, odzywianie) są tam tabele z innych zadań; zostawiasz je, zadanie ich nie dotyczy.
Struktura z obrazu 1: tabela zwierzeta ma pola id, Gromady_id, Odzywianie_id, gatunek, wystepowanie, czy_zagrozony i obraz. Pola Gromady_id i Odzywianie_id to klucze obce - wskazują wiersz w tabelach gromady (1 ryby, 2 płazy, 3 gady, 4 ptaki, 5 ssaki) i odzywianie. Tabela zwierzeta ma 9 wierszy.
Po imporcie widać zielony komunikat o sukcesie i listę tabel w lewym panelu - to jest „element wskazujący na poprawny import”. Zrzut całego ekranu z paskiem zadań zapisujesz jako import.png.
Typowe błędy
Ten zrzut ma format PNG (zrzuty kwerend - JPG). Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).
Podgląd strony po tym kroku
Krok 4: Zapytanie 1: gatunki i występowanie ryb
Kryteria: ,
R.1.2 Zapisano plik kwerendy.txt zawierający co najmniej jedno zapytanieami SQL wynikające z treści zadania
R.1.3 Wykonano zapytanie 1 wybierające jedynie pola gatunek i wystepowanie z tabeli Zwierzeta jedynie dla ryb. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT gatunek, wystepowanie FROM zwierzeta WHERE Gromady_id = 1; oraz wynik działania udokumentowano zrzutem, na którym widoczne są dokładnie 2 rekordy dla suma i jesiotra, wyświetlone jedynie kolumny gatunek, wystepowanie
ok. 4 min
Polecenie z arkusza
Zapisz i wykonaj zapytania SQL działające na bazie danych. Zapytania zapisz w pliku kwerendy.txt, w folderze z numerem PESEL. Wykonaj zrzuty ekranu przedstawiające wyniki działania kwerend. Zrzuty zapisz w formacie JPG i nadaj im nazwy kw1, kw2, kw3, kw4. Zrzuty powinny obejmować cały ekran monitora z widocznym paskiem zadań. Zapytanie 1: wybierające jedynie pola gatunek i wystepowanie z tabeli Zwierzeta jedynie dla ryb
Karta SQL bazy baza. Zapytanie klauzula po klauzuli:
SELECT gatunek, wystepowanie - „jedynie pola” wyklucza SELECT *; nazwa wystepowanie bez polskiej litery, tak jak w tabeli,
FROM zwierzeta,
WHERE Gromady_id = 1 - ryby to gromada o identyfikatorze 1 (tabela gromady na obrazie 1). Warunek idzie po kluczu obcym, nie po nazwie.
Wynik: 2 wiersze - Sum pospolity, Eurazja i Jesiotr zachodni, Europa, dokładnie jak w kluczu. Zapytanie kopiujesz do pliku kwerendy.txt (Notatnik, jedno zapytanie pod drugim), a cały ekran z wynikiem zapisujesz jako kw1.jpg (Print Screen, wklejenie do edytora grafiki, zapis jako JPEG).
To zapytanie jest wzorem dla skryptu nr 1: w miejsce 1 trafi numer gromady wpisany w formularzu.
Typowe błędy
WHERE nazwa = 'ryby' nie zadziała - tabela zwierzeta nie ma kolumny z nazwą gromady, ma tylko jej numer. Zrzuty kwerend zapisuj w JPG, nie w PNG.
kwerendy.txtTekstnowy plik
-- Zapytanie 1SELECT gatunek, wystepowanie FROM zwierzeta WHERE Gromady_id = 1;
Podgląd strony po tym kroku
Krok 5: Zapytanie 2: zwierzęta z nazwą gromady (relacja)
Kryteria:
R.1.4 Wykonano zapytanie 2 wybierające jedynie pola id i gatunek z tabeli Zwierzeta oraz odpowiadające im pole nazwa z tabeli Gromady. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT zwierzeta.id, gatunek, nazwa FROM zwierzeta JOIN gromady ON zwierzeta.Gromady_id = gromady.id; możliwe również INNER JOIN lub SELECT zwierzeta.id, gatunek, gromady.nazwa FROM zwierzeta, gromady WHERE gromady.id = zwierzeta.gromady_id; oraz wynik działania udokumentowano zrzutem, na którym widoczne jest dokładnie 9 rekordów o id= 1 - 9, jedynie pola id, gatunek, nazwa
ok. 3 min
Polecenie z arkusza
Zapytanie 2: wybierające jedynie pola id i gatunek z tabeli Zwierzeta oraz odpowiadające im pole nazwa z tabeli Gromady. Należy posłużyć się relacją.
SELECT zwierzeta.id, gatunek, nazwa - kolumna id jest w obu tabelach, więc trzeba wskazać, z której: zwierzeta.id. gatunek i nazwa są jednoznaczne,
FROM zwierzeta JOIN gromady - złączenie dwóch tabel,
ON zwierzeta.Gromady_id = gromady.id - relacja: klucz obcy zwierzęcia równa się kluczowi głównemu gromady. Dla każdego zwierzęcia baza dobiera jego gromadę.
Wynik: 9 wierszy o id 1-9, od Sum pospolity, ryby do Dingo australijski, ssaki. Klucz przyjmuje też INNER JOIN i zapis z przecinkiem i warunkiem w WHERE. Zrzut: kw2.jpg. To zapytanie wyśle skrypt nr 2.
Typowe błędy
Samo SELECT id, ... przy złączeniu kończy się błędem #1052 „Column id in field list is ambiguous” - kolumna o tej nazwie jest w obu tabelach. Bez warunku ON baza zwróci 45 wierszy (każde zwierzę z każdą gromadą).
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT gatunek, wystepowanie FROM zwierzeta WHERE Gromady_id = 1;-- Zapytanie 2SELECT zwierzeta.id, gatunek, nazwa FROM zwierzeta JOIN gromady ON zwierzeta.Gromady_id = gromady.id;
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: liczba ssaków
Kryteria:
R.1.5 Wykonano zapytanie 3 zliczające liczbę rekordów w tabeli Zwierzeta jedynie dla ssaków. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT COUNT(*) FROM zwierzeta WHERE Gromady_id = 5; oraz wynik działania udokumentowano zrzutem, na którym widoczny jest wynik działania kwerendy - wartość 4
ok. 2 min
Polecenie z arkusza
Zapytanie 3: zliczające liczbę rekordów w tabeli Zwierzeta jedynie dla ssaków
COUNT(*) to funkcja agregująca - zamiast wierszy zwraca ich liczbę. WHERE Gromady_id = 5 ogranicza liczenie do ssaków (gromada 5). Wynik: jedna komórka z wartością 4 (wilk, hiena, sarna, dingo). Zrzut: kw3.jpg.
Typowe błędy
SUM(Gromady_id) doda numery gromad (5 + 5 + 5 + 5 = 20), a nie policzy rekordów. Do liczenia wierszy służy COUNT.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT gatunek, wystepowanie FROM zwierzeta WHERE Gromady_id = 1;-- Zapytanie 2SELECT zwierzeta.id, gatunek, nazwa FROM zwierzeta JOIN gromady ON zwierzeta.Gromady_id = gromady.id;-- Zapytanie 3SELECT COUNT(*) FROM zwierzeta WHERE Gromady_id = 5;
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: użytkownik KatarzynaNowak
Kryteria:
R.1.6 Wykonano zapytanie 4 tworzące użytkownika KatarzynaNowak o haśle K4tNow. W pliku z kwerendami lub na zrzucie istnieje zapis z jawnie zapisanym hasłem np.: CREATE USER 'KatarzynaNowak'@'localhost' IDENTIFIED BY 'K4tNow'; lub CREATE USER 'KatarzynaNowak'@'%' IDENTIFIED BY 'K4tNow'; oraz wynik działania udokumentowano zrzutem, na którym widoczne jest potwierdzenie utworzenia konta użytkownika. Nie uznajemy automatycznego utworzenia konta
ok. 2 min
Polecenie z arkusza
Zapytanie 4: tworzące użytkownika KatarzynaNowak o haśle K4tNow
CREATE USER - polecenie tworzące konto serwera bazy danych (nie wiersz w tabeli),
'KatarzynaNowak'@'localhost' - nazwa użytkownika i host, z którego może się łączyć; klucz przyjmuje też '%' (dowolny host),
IDENTIFIED BY 'K4tNow' - hasło zapisane jawnie w zapytaniu; serwer sam zapisze je w postaci zaszyfrowanej.
phpMyAdmin odpowiada „MySQL zwrócił pusty wynik (np. zero rekordów)” - CREATE USER niczego nie wybiera, więc to znak sukcesu. Zrzut z zapytaniem i komunikatem: kw4.jpg. Plik kwerendy.txt ma komplet czterech zapytań.
Typowe błędy
Konto założone w zakładce Konta użytkowników (bez zapytania SQL) nie jest uznawane - klucz wymaga kwerendy. Drugie wykonanie tego samego CREATE USER kończy się błędem #1396, bo konto już istnieje.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT gatunek, wystepowanie FROM zwierzeta WHERE Gromady_id = 1;-- Zapytanie 2SELECT zwierzeta.id, gatunek, nazwa FROM zwierzeta JOIN gromady ON zwierzeta.Gromady_id = gromady.id;-- Zapytanie 3SELECT COUNT(*) FROM zwierzeta WHERE Gromady_id = 5;-- Zapytanie 4CREATE USER 'KatarzynaNowak'@'localhost' IDENTIFIED BY 'K4tNow';
Podgląd strony po tym kroku
Etap 2: Strona HTML
Kroki 8-22 · po tym etapie masz 19 z 36 kryteriów (pkt)
Krok 8: Plik index.php
ok. 2 min
Polecenie z arkusza
Składa się ze strony o nazwie index.php
Plik index.php w folderze zdającego, obok zwierzeta.jpg. Rozszerzenie .php, bo dojdą skrypty - na razie to czysty HTML. <!DOCTYPE html> oznacza HTML5, lang="pl" mówi przeglądarce i czytnikom ekranu, że treść jest po polsku. Do sprawdzania strony kopiujesz folder do C:\xampp\htdocs (albo tam pracujesz i na końcu kopiujesz pliki do folderu zdającego) i otwierasz http://localhost/…/index.php.
R.2.1 Witrynę internetową zapisano w pliku index.php oraz zastosowano właściwy standard kodowania polskich znaków
ok. 1 min
Polecenie z arkusza
Zastosowany właściwy standard kodowania polskich znaków
<meta charset="UTF-8"> jako pierwsza rzecz w <head>. Bez tej linii „ATLAS ZWIERZĄT” i „Płazy” mogą wyświetlić się jako krzaki. Plik trzeba też zapisać w UTF-8 (w Notepad++ menu Kodowanie). Nazwa pliku i kodowanie dają razem R.2.1.
R.2.2 Nadano tytuł strony: "Dane o zwierzętach”, jest on widoczny na karcie przeglądarki
ok. 1 min
Polecenie z arkusza
Tytuł strony widoczny na karcie przeglądarki: „Dane o zwierzętach”
<title> w <head> - napis na karcie przeglądarki. Tytuł („Dane o zwierzętach”) i nagłówek banera („ATLAS ZWIERZĄT”) to dwa różne teksty.
index.phpPHPzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Dane o zwierzętach</title></head><body></body></html>
Podgląd strony po tym kroku (index.php)
Krok 11: Podpięcie arkusza stylów styl3.css
Kryteria:
R.3.6 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl3.css lub style.css , formatowanie pochodzi jedynie z tego arkusza Uwaga: kryterium to nie jest spełnione również, gdy źle przypisano co najmniej jeden selektor do bloku (np. kropka zamiast #)
ok. 1 min
Polecenie z arkusza
Arkusz stylów w pliku o nazwie styl3.css prawidłowo połączony z kodem strony
<link rel="stylesheet" href="styl3.css"> w <head>. Nazwa ma w sobie cyfrę: styl3.css. Plik stylów powstanie po HTML-u; od tej chwili całe formatowanie ma pochodzić z niego (R.3.6) - bez atrybutów style w znacznikach.
⚠️ Sprzeczność w arkuszu: w tym wydaniu cechy witryny mówią o pliku styl3.css, a nagłówek części o stylach - że styl ma być „w całości w zewnętrznym pliku o nazwie style.css”. Lista plików do nagrania na płytę znów wymienia styl3.css. Klucz (R.3.6) przyjmuje obie nazwy, więc wystarczy jeden plik - tutaj styl3.css, jak w dwóch z trzech miejsc arkusza.
Typowe błędy
Zła nazwa w href to brak stylów. Klucz odbiera R.3.6 także wtedy, gdy choć jeden selektor nie trafia w blok (np. kropka zamiast # przy identyfikatorze).
index.phpPHPzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Dane o zwierzętach</title> <linkrel="stylesheet"href="styl3.css"></head><body></body></html>
Podgląd strony po tym kroku (index.php)
Krok 12: Bloki: baner, formularz, trzy główne i stopka
Kryteria:
R.2.3 Wygląd strony zdefiniowano dzieląc ją na bloki: na górze baner, poniżej blok formularza, poniżej trzy bloki główne: lewy, środkowy i prawy, na dole blok stopki. Zastosowano znaczniki sekcji
ok. 2 min
Polecenie z arkusza
Podział strony na bloki: na górze baner, poniżej blok formularza, poniżej trzy bloki główne: lewy, środkowy i prawy, na dole blok stopki. Podział zrealizowany za pomocą znaczników sekcji tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z obrazem 2
Sześć bloków w kolejności z obrazu 2: baner <header>, blok formularza i trzy bloki główne jako <section>, stopka <footer> - to są „znaczniki sekcji” HTML5 (R.2.3). Sekcje różnią się wyglądem, więc dostają identyfikatory: form-block, left, middle i right (nazwy po angielsku - arkusz ich nie narzuca). Na razie bloki są puste i stoją jeden pod drugim; trzy główne ustawi obok siebie CSS.
Typowe błędy
Bloki z samych <div> bez znaczników sekcji nie spełniają R.2.3 - klucz wymaga znaczników sekcji (header, section, footer...).
Zawartość banera: nagłówek pierwszego stopnia „ATLAS ZWIERZĄT”
<h1> w <header>, tekst wielkimi literami jak w arkuszu. Klucz R.2.4 sprawdza go razem z dwoma nagłówkami <h2> - punkt przyjdzie po nagłówku bloku prawego.
R.2.5 W bloku formularza umieszczono listę numerowaną o elementach: „Ryby”, „Płazy”, „Gady”, „Ptaki”, „Ssaki” oraz zastosowano znaczniki <ol>, <li>
ok. 1 min
Polecenie z arkusza
Lista numerowana o elementach: „Ryby”, „Płazy”, „Gady”, „Ptaki”, „Ssaki”
Lista numerowana to <ol> (ordered list), każdy element w <li> z zamknięciem </li> (R.2.5). Numery 1-5 dopisuje przeglądarka - w tekście ich nie wpisujesz. Kolejność gromad nie jest przypadkowa: numer na liście to ten sam numer, który ma gromada w tabeli gromady, więc uczeń wie, co wpisać w pole formularza.
Typowe błędy
<ul> to lista wypunktowana (kropki zamiast numerów) - klucz wymaga znaczników <ol> i <li>.
R.3.2 Formularz przesyła dane metodą POST (poprawne również bez atrybutu action)
ok. 1 min
Polecenie z arkusza
Formularz wysyłający dane metodą POST do tej samej strony z elementami
<form method="post"> - bez atrybutu action formularz wysyła dane do tego samego adresu, z którego został wczytany, czyli do index.php („do tej samej strony”). Metoda POST przesyła dane w treści żądania, nie w adresie strony; w PHP odczytasz je z tablicy $_POST (R.3.2).
Typowe błędy
Bez method="post" formularz użyje metody GET - wartość trafi do adresu (index.php?gromada=4), a skrypt czytający $_POST niczego nie dostanie.
Krok 17: Tekst „Wybierz gromadę: ” i pole numeryczne
ok. 1 min
Polecenie z arkusza
Tekst „Wybierz gromadę: ” Pole edycyjne typu numerycznego
Tekst wprost w formularzu, a za nim <input type="number"> - pole numeryczne: przyjmuje tylko liczby i ma strzałki do zmiany wartości, jak na obrazie 2. Atrybut name="gromada" to klucz, pod którym wartość trafi do PHP: $_POST['gromada'].
Typowe błędy
type="text" wygląda podobnie, ale nie jest polem typu number - klucz sprawdza typ pola (R.3.3).
R.2.6 W bloku formularza umieszczono formularz z polem do wprowadzania danych oraz przyciskiem opisanym "Wyświetl"
R.3.3 Pole formularza jest typu number oraz przycisk jest typu submit
ok. 1 min
Polecenie z arkusza
Przycisk wysyłający dane o nazwie „Wyświetl”
<input type="submit" value="Wyświetl"> - przycisk, który wysyła formularz; napis na nim to wartość value. Formularz ma komplet: pole i przycisk (R.2.6), pole jest typu number, a przycisk typu submit - wysyła dane (R.3.3).
Typowe błędy
<input type="button"> wygląda tak samo, ale niczego nie wysyła - skrypt nr 1 nigdy nie dostanie wartości.
Krok 19: Blok lewy: zdjęcie z tekstem alternatywnym
Kryteria:
R.2.7 W bloku głównym - lewym umieszczono obraz zwierzeta.jpg oraz ma on tekst alternatywny "dzikie zwierzeta"
ok. 1 min
Polecenie z arkusza
Zawartość bloku głównego – lewego: obraz zwierzeta.jpg z wypakowanego archiwum, z tekstem alternatywnym „dzikie zwierzęta”
<img> z atrybutami src (nazwa pliku z folderu zdającego) i alt - tekst, który czytnik ekranu przeczyta zamiast zdjęcia i który pokaże się, gdy plik się nie wczyta (R.2.7). Zdjęcie z archiwum ma 400 × 300 px i trafia na stronę bez zmian - arkusz nie każe go przerabiać.
Krok 20: Blok prawy: nagłówek „Wszystkie zwierzęta w bazie”
Kryteria:
R.2.4 W bloku banera zapisano nagłówek h1: "ATLAS ZWIERZĄT" oraz w bloku formularza zapisano nagłówek h2: "Gromady:" oraz w bloku głównym - prawym nagłówek h2: „Wszystkie zwierzęta w bazie”
ok. 1 min
Polecenie z arkusza
Zawartość bloku głównego – prawego: Nagłówek drugiego stopnia o treści „Wszystkie zwierzęta w bazie”
Drugi <h2>. Strona ma już nagłówek <h1> w banerze, <h2> w bloku formularza i <h2> w bloku prawym (R.2.4). Pod tym nagłówkiem wypisze swój wynik skrypt nr 2; blok środkowy zostaje na razie pusty - wypełni go skrypt nr 1.
Krok 21: Stopka: odnośnik otwierany w nowej karcie
Kryteria: ,
R.3.4 Na stronie znajduje się odnośnik o treści "Poznaj inne strony o zwierzętach", jego kliknięcie inicjuje otwarcie strony "atlas-zwierzat.pl"
R.3.5 Strona jest otwierana w osobnym oknie / zakładce przeglądarki
ok. 1 min
Polecenie z arkusza
Zawartość stopki: Odnośnik o treści „Poznaj inne strony o zwierzętach” prowadzący do strony „atlas-zwierzat.pl”, odnośnik otwiera stronę w osobnej karcie
<a href="https://atlas-zwierzat.pl"> - adres z protokołemhttps://. Sam atlas-zwierzat.pl przeglądarka potraktuje jak nazwę pliku w folderze strony (klucz przyjmuje obie formy - R.3.4). Atrybut target="_blank" otwiera stronę w nowej karcie (R.3.5).
Typowe błędy
target="blank" (bez podkreślenia) też otworzy nową kartę, ale nazwaną „blank” - kolejne kliknięcie trafi do tej samej karty. Wartość z arkusza „w osobnej karcie” to _blank.
index.phpPHPzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Dane o zwierzętach</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <h1>ATLAS ZWIERZĄT</h1> </header> <sectionid="form-block"> <h2>Gromady:</h2> <ol> <li>Ryby</li> <li>Płazy</li> <li>Gady</li> <li>Ptaki</li> <li>Ssaki</li> </ol> <formmethod="post"> Wybierz gromadę: <inputtype="number"name="gromada"> <inputtype="submit"value="Wyświetl"> </form> </section> <sectionid="left"> <imgsrc="zwierzeta.jpg"alt="dzikie zwierzęta"> </section> <sectionid="middle"> </section> <sectionid="right"> <h2>Wszystkie zwierzęta w bazie</h2> </section> <footer> <ahref="https://atlas-zwierzat.pl"target="_blank">Poznaj inne strony o zwierzętach</a> </footer></body></html>
Podgląd strony po tym kroku (index.php)
Krok 22: Stopka: autor strony
Kryteria:
R.2.8 W stopce zapisano tekst "autor Atlasu zwierząt: " oraz wstawiono numer PESEL
ok. 1 min
Polecenie z arkusza
Napis o treści „autor Atlasu zwierząt: ”, dalej wstawiony numer zdającego
Napis stoi zaraz za odnośnikiem, w tej samej linii - jak na obrazie 2. Na egzaminie po dwukropku wpisujesz swój numer zdającego. W tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora: Bartosz Bryniarski (R.2.8).
index.phpPHPzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Dane o zwierzętach</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <h1>ATLAS ZWIERZĄT</h1> </header> <sectionid="form-block"> <h2>Gromady:</h2> <ol> <li>Ryby</li> <li>Płazy</li> <li>Gady</li> <li>Ptaki</li> <li>Ssaki</li> </ol> <formmethod="post"> Wybierz gromadę: <inputtype="number"name="gromada"> <inputtype="submit"value="Wyświetl"> </form> </section> <sectionid="left"> <imgsrc="zwierzeta.jpg"alt="dzikie zwierzęta"> </section> <sectionid="middle"> </section> <sectionid="right"> <h2>Wszystkie zwierzęta w bazie</h2> </section> <footer> <ahref="https://atlas-zwierzat.pl"target="_blank">Poznaj inne strony o zwierzętach</a> autor Atlasu zwierząt: Bartosz Bryniarski </footer></body></html>
Podgląd strony po tym kroku (index.php)
Etap 3: Styl CSS
Kroki 23-30 · po tym etapie masz 28 z 36 kryteriów (pkt)
Krok 23: Plik styl3.css: krój Garamond dla całej strony
Kryteria:
R.4.1 Ustawiono domyślny (*) krój czcionki dla całej strony na Garamond
ok. 1 min
Polecenie z arkusza
Styl CSS zdefiniowany w całości w zewnętrznym pliku o nazwie style.css. Styl CSS zawiera formatowanie: Domyślne formatowanie wszystkich selektorów: krój czcionki Garamond
Nowy plik styl3.css w folderze zdającego - od teraz każda reguła trafia tylko tutaj. Pierwsza reguła: selektor uniwersalny * z font-family: Garamond.
Dlaczego *, a nie body: pola formularza i przyciski nie dziedziczą kroju po body, a na obrazie 2 napis „Wyświetl” na przycisku jest pisany Garamondem. Starsze wydania klucza przyjmują też body i html, wydanie z czerwca 2023 pisze wprost „(*)” - selektor * jest bezpieczny zawsze (R.4.1).
Dla bloku banera: kolor tła RosyBrown, biały kolor czcionki, wyrównanie tekstu do środka, marginesy wewnętrzne 10 px
Selektor znacznika header - na stronie jest jeden baner. RosyBrown i white to nazwy kolorów CSS (wielkość liter bez znaczenia) - wpisuj je dosłownie, przeglądarka zna je bez zamiany na kod szesnastkowy. „Marginesy wewnętrzne” to padding (zewnętrzne to margin).
Dla bloku formularza: kolor tła DarkSalmon, wyrównanie tekstu do środka, marginesy wewnętrzne 40 px
Selektor identyfikatora #form-block - z krzyżykiem, bo w HTML-u jest id="form-block". Wyśrodkowanie dziedziczą nagłówek, numery listy i formularz, dlatego na obrazie 2 cała zawartość bloku stoi pośrodku.
R.4.4 Ustawiono wysokość dla trzech bloków głównych 300px
R.4.5 Ustawiono szerokość bloku głównego prawego i lewego 30% oraz głównego środkowego na 40%
ok. 1 min
Polecenie z arkusza
Dla bloku głównego – środkowego: kolor tła LightSalmon, wysokość 300 px, szerokość 40%
Szerokości 30% + 40% + 30% = 100% - trzy bloki zajmą razem całą szerokość strony. Wysokości wszystkich trzech bloków głównych (R.4.4) i ich szerokości (R.4.5) są ustawione.
Typowe błędy
Bloki o sumie szerokości 100% nie mogą mieć marginesów, padding ani obramowań - każdy piksel więcej zepchnie blok prawy pod spód.
R.4.2 Ustawiono kolor tła RosyBrown dla bloku banera i stopki oraz DarkSalmon dla bloku formularza oraz LightSalmon dla trzech bloków głównych
R.4.3 Ustawiono biały kolor czcionki dla banera i stopki
R.4.6 Ustawiono wyrównanie tekstu do środka dla bloku banera, formularza i stopki
R.4.7 Ustawiono marginesy wewnętrzne (padding) 10px dla banera oraz 40px dla formularza oraz 30px dla stopki
ok. 1 min
Polecenie z arkusza
Dla stopki: kolor tła RosyBrown, biały kolor czcionki, wyrównanie tekstu do środka, marginesy wewnętrzne 30 px
Ten sam kolor co w banerze. Komplet: kolory tła wszystkich bloków (R.4.2), biały tekst banera i stopki (R.4.3), wyśrodkowanie banera, formularza i stopki (R.4.6), marginesy wewnętrzne 10, 40 i 30 px (R.4.7).
Biały kolor nie obejmuje odnośnika - przeglądarka ma dla <a> własny kolor (fioletowy po odwiedzeniu, niebieski przed), dlatego na obrazie 2 odnośnik w stopce jest fioletowy, a napis o autorze biały.
Krok 29: Lista numerowana: obramowanie i rozmiar czcionki
Kryteria:
R.4.8 Ustawiono styl listy numerowanej: obramowanie 2px linią ciągłą w kolorze rgb(205, 92, 92) lub #CD5C5C oraz rozmiar czcionki 150%
ok. 1 min
Polecenie z arkusza
Dla listy numerowanej: obramowanie 2 px linią ciągłą w kolorze RGB: 205, 92, 92; rozmiar czcionki 150%
Selektor znacznika ol. Skrót border łączy grubość (2px), styl (solid - linia ciągła) i kolor - zapis rgb(205, 92, 92) to dokładnie wartości z arkusza (ten sam kolor ma nazwę IndianRed i kod #CD5C5C, klucz przyjmuje rgb i kod). font-size: 150% - półtora raza większe litery niż w bloku (R.4.8).
R.3.1 Układ bloków na stronie po uruchomieniu w przeglądarce jest zgodny z Obrazem 2 w arkuszu egzaminacyjnym (prawidłowo zastosowano właściwości CSS układające bloki na stronie, np. float i clear albo display flex albo grid)
ok. 3 min
Polecenie z arkusza
Podział strony na bloki: na górze baner, poniżej blok formularza, poniżej trzy bloki główne: lewy, środkowy i prawy, na dole blok stopki. Podział zrealizowany za pomocą znaczników sekcji tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z obrazem 2
Sekcje dostają float: left - bloki główne (30% + 40% + 30%) stają obok siebie w jednym rzędzie. Blok formularza też jest sekcją, ale ma zajmować całą szerokość, więc reguła #form-block zdejmuje z niego opływanie (float: none) - identyfikator jest silniejszy niż sam znacznik, więc wygrywa niezależnie od kolejności. Stopka z clear: both zaczyna się dopiero pod pływającymi blokami.
Zdjęcie ma 400 px szerokości, a blok lewy 30% okna: przy oknie szerszym niż ok. 1350 px mieści się w całości (jak na obrazie 2), przy węższym jego prawy brzeg chowa się pod blokiem środkowym. Arkusz nie każe zmieniać rozmiaru zdjęcia - a reguła dla img wykraczałaby poza cechy formatowania z arkusza. Klucz R.3.1 sprawdza układ bloków.
Typowe błędy
Bez float: none dla bloku formularza (albo bez osobnego znacznika dla niego) blok formularza też popłynie w lewo i trzy bloki główne ustawią się obok niego. Bez clear: both stopka wsunie się pod pływające bloki.
Kroki 31-38 · po tym etapie masz 36 z 36 kryteriów (pkt)
Krok 31: Blok środkowy: miejsce skryptu i połączenie z bazą
Kryteria: ,
R.5.1 Skrypt napisano w języku PHP i zawiera przynajmniej jedną instrukcję
R.5.2 Skrypt realizuje połączenie z serwerem bazy danych i wybór bazy baza
ok. 3 min
Polecenie z arkusza
Zawartość bloku głównego – środkowego: efekt wykonania skryptu nr 1 Napisany w języku PHP Skrypt łączy się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie baza
„Efekt wykonania skryptu nr 1” ma być w bloku środkowym, więc tam piszesz blok PHP, między <?php a ?>. Serwer wykona go, zanim strona trafi do przeglądarki (R.5.1).
Pierwsza instrukcja: mysqli_connect z tabeli 1 arkusza - kolejno serwer localhost, użytkownik root, puste hasło '' i nazwa bazy baza (R.5.2). Połączenie trafia do zmiennej $connection. Wystarczy jedno połączenie na całą stronę - skrypt nr 2 w bloku prawym skorzysta z tej samej zmiennej, bo PHP wykonuje wszystkie bloki jednego pliku po kolei.
Od tego kroku podgląd to wynik działania strony po stronie serwera (prawdziwe uruchomienie w PHP 8.2) - na razie wygląda jak wcześniej. Stronę sprawdzasz przez http://localhost/…, a nie otwierając plik z dysku: przeglądarka sama nie wykona PHP.
index.phpPHPzmienione: 3 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Dane o zwierzętach</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <h1>ATLAS ZWIERZĄT</h1> </header> <sectionid="form-block"> <h2>Gromady:</h2> <ol> <li>Ryby</li> <li>Płazy</li> <li>Gady</li> <li>Ptaki</li> <li>Ssaki</li> </ol> <formmethod="post"> Wybierz gromadę: <inputtype="number"name="gromada"> <inputtype="submit"value="Wyświetl"> </form> </section> <sectionid="left"> <imgsrc="zwierzeta.jpg"alt="dzikie zwierzęta"> </section> <sectionid="middle"><?php$connection = mysqli_connect('localhost', 'root', '', 'baza');?> </section> <sectionid="right"> <h2>Wszystkie zwierzęta w bazie</h2> </section> <footer> <ahref="https://atlas-zwierzat.pl"target="_blank">Poznaj inne strony o zwierzętach</a> autor Atlasu zwierząt: Bartosz Bryniarski </footer></body></html>
Podgląd strony po tym kroku (index.php)
Krok 32: Skrypt nr 1: wartość z pola edycyjnego
ok. 2 min
Polecenie z arkusza
Działanie skryptu nr 1: Skrypt pobiera dane z pola edycyjnego
isset($_POST['gromada']) jest prawdziwe dopiero po kliknięciu „Wyświetl”. Przy pierwszym wejściu na stronę formularz nie był wysłany i skrypt nr 1 nic nie robi - blok środkowy jest pusty,
$gromada = $_POST['gromada']; - wartość pola (klucz to atrybut name) trafia do zmiennej o czytelnej nazwie.
Od tego kroku podgląd pokazuje stronę po wysłaniu formularza z wartością 4, jak na obrazie 2. Na razie nic jeszcze nie widać - wartość jest tylko odczytana.
Typowe błędy
Odczyt $_POST['gromada'] bez isset przy pierwszym wejściu na stronę daje ostrzeżenie „Undefined array key” wypisane na stronie.
R.5.5 Skrypt wypisuje w nagłówku h2 tekst zależny od podanej wartości w polu. Jeśli podano 1 – „RYBY”, 2 – „PŁAZY”, 3 – „GADY”, 4 – „PTAKI”, 5 – „SSAKI”
ok. 3 min
Polecenie z arkusza
W zależności od wartości pola wypisuje w nagłówku drugiego stopnia: dla wartości 1 – „RYBY”, 2 – „PŁAZY”, 3 – „GADY”, 4 – „PTAKI”, 5 – „SSAKI”
Pięć wartości, pięć napisów - drabinka if / elseif: pierwszy prawdziwy warunek wypisuje swój nagłówek, reszta jest pomijana. Napis idzie w znaczniku <h2> (R.5.5). Porównanie == porównuje wartość, a nie typ: z formularza przychodzi napis '4', a '4' == 4 jest w PHP prawdziwe.
Podgląd: wartość 4 - w bloku środkowym nagłówek PTAKI. Dla wartości spoza 1-5 (np. 7) żaden warunek nie jest prawdziwy i nagłówka nie ma - arkusz nie mówi, co wtedy wypisać.
Typowe błędy
if ($gromada = 1) z jednym znakiem równości to przypisanie, nie porównanie - warunek zawsze jest prawdziwy i dla każdej wartości wypisze się „RYBY”.
R.5.4 Skrypt nr 1 zawiera instrukcję wysyłającą do bazy zmodyfikowane zapytanie nr 1, w ten sposób, że w sekcji warunku sprawdzana gromada jest zgodna z wartością w polu formularza. Jeśli w polu wpisana jest wartość 1 – zapytanie dotyczy ryb, wartość 2 – zapytanie dotyczy płazów itd.
ok. 2 min
Polecenie z arkusza
Wysyła do bazy zmodyfikowane zapytanie nr 1, w ten sposób, że w sekcji warunku sprawdzana gromada jest zgodna z wartością pobraną z pola edycyjnego. Jeśli w polu wpisana jest wartość 1 – zapytanie dotyczy ryb, wartość 2 – zapytanie dotyczy płazów itd.
Zapytanie 1 z kwerendy.txt z jedną zmianą: w miejsce 1 w warunku stoi $gromada. Całe zapytanie jest w cudzysłowie "…", więc PHP podstawia wartość zmiennej - dla 4 baza dostaje WHERE Gromady_id = 4. Numery na liście w bloku formularza są tymi samymi numerami co id w tabeli gromady, dlatego wartość z pola można wstawić do warunku bez żadnej zamiany (R.5.4).
Wynik mysqli_query trafia do $result - jeszcze nic nie jest wypisane. Zapytanie stoi w tym samym warunku co nagłówek: wysyła się tylko po wysłaniu formularza.
Typowe błędy
Zapytanie w apostrofach '… Gromady_id = $gromada;' - PHP nie podstawi zmiennej i baza dostanie dosłownie tekst $gromada, co kończy się błędem składni SQL.
Krok 35: Skrypt nr 1: gatunek i występowanie w osobnych wierszach
Kryteria:
R.5.6 Skrypt nr 1 wypisuje zwrócone zapytaniem rekordy w osobnych wierszach, w formacie „<gatunek>, <występowanie>” Dane muszą być pobrane z bazy danych
ok. 3 min
Polecenie z arkusza
Wartości zwrócone zapytaniem są wypisywane w osobnych wierszach, w formacie „<gatunek>, <występowanie>”
mysqli_fetch_row($result) zwraca kolejny wiersz wyniku jako tablicę numerowaną od zera: $row[0] to gatunek, $row[1] - wystepowanie (kolejność kolumn z SELECT). Gdy wierszy zabraknie, zwraca false i pętla while się kończy,
echo "$row[0], $row[1]<br>"; - format z arkusza: gatunek, przecinek, spacja, występowanie; <br> przenosi kolejny rekord do nowego wiersza (R.5.6).
Podgląd: trzy ptaki z bazy - Wrona siwa, Europa, Puszczyk zwyczajny, Eurazja, Sroka zwyczajna, Eurazja, dokładnie jak na obrazie 2.
Typowe błędy
Bez <br> wszystkie rekordy skleją się w jedną linię - przeglądarka ignoruje znaki nowej linii z PHP.
R.5.7 Skrypt nr 2 zawiera instrukcję wysyłającą do bazy zapytanie 2
ok. 2 min
Polecenie z arkusza
Zawartość bloku głównego – prawego: Efekt wykonania skryptu nr 2 Działanie skryptu nr 2: Skrypt wysyła do bazy zapytanie numer 2
Drugi blok PHP stoi w bloku prawym, pod nagłówkiem „Wszystkie zwierzęta w bazie”. Korzysta z połączenia $connection otwartego w bloku środkowym. Zapytanie 2 z kwerendy.txt bez zmian (R.5.7) - tu nie ma żadnej zmiennej, więc wystarczą apostrofy. Skrypt nr 2 działa zawsze, także przed wysłaniem formularza.
Krok 37: Skrypt nr 2: rekordy w formacie „id. gatunek, gromada”
Kryteria:
R.5.8 Skrypt nr 2 wypisuje w kolejnych wierszach rekordy w formacie: „<id>. <gatunek>, <nazwa gromady>. Dane muszą być pobrane z bazy danych
ok. 2 min
Polecenie z arkusza
W kolejnych wierszach wypisywane są rekordy w formacie: „<id>. <gatunek>, <nazwa gromady>”
Ta sama pętla co w skrypcie nr 1, tylko z trzema kolumnami: $row[0] - id, $row[1] - gatunek, $row[2] - nazwa gromady. Po numerze kropka i spacja, po gatunku przecinek i spacja (R.5.8).
Podgląd: dziewięć zwierząt, od 1. Sum pospolity, ryby do 9. Dingo australijski, ssaki. Nazwy gromad są w bazie zapisane małymi literami i bez polskich znaków (plazy) - strona wypisuje je tak, jak są w tabeli.
R.5.3 Po wykonaniu operacji na bazie zastosowano funkcję zamknięcia bazy
ok. 1 min
Polecenie z arkusza
Na końcu działania skrypt zamyka połączenie z serwerem bazodanowym
mysqli_close($connection) na końcu bloku PHP w bloku prawym - po ostatnim zapytaniu na stronie, poza warunkami, więc wykona się zawsze (R.5.3). Strona spełnia wszystkie kryteria arkusza; podgląd pokazuje stan z obrazu 2. Dalej trzy kroki o zabezpieczeniach - klucz ich nie wymaga.
Typowe błędy
mysqli_close w bloku środkowym (zaraz po skrypcie nr 1) zamknie połączenie, zanim skrypt nr 2 wyśle swoje zapytanie - PHP 8 zgłosi wtedy błąd „mysqli object is already closed”.
Kroki 39-41 · po tym etapie masz 36 z 36 kryteriów (pkt)
Krok 39: Zabezpieczenie: zapytanie przygotowane
ok. 4 min
Polecenie z arkusza
Wysyła do bazy zmodyfikowane zapytanie nr 1, w ten sposób, że w sekcji warunku sprawdzana gromada jest zgodna z wartością pobraną z pola edycyjnego.
Wartość z formularza trafia do zapytania wprost - to SQL injection. Pole type="number" nie chroni: ogranicza tylko to, co da się wpisać w przeglądarce, a żądanie POST można wysłać z dowolną treścią (np. narzędziami deweloperskimi albo programem curl). Sprawdzone na wersji z poprzednich kroków:
wartość 0 OR 1=1 zamienia warunek w zawsze prawdziwy - blok środkowy wypisuje wszystkie dziewięć zwierząt,
wartość 0 UNION SELECT imie, nazwisko FROM pracownicy dokleja wynik z innej tabeli - w bloku środkowym pojawiają się imiona i nazwiska pracowników (Anna, Kowalska …), czyli dane, których strona nigdy nie miała pokazywać,
puste pole rozbija składnię zapytania (WHERE Gromady_id = ;) - PHP 8 zgłasza wyjątek mysqli_sql_exception i zamiast strony widać „Fatal error”.
Lekarstwo to zapytanie przygotowane: mysqli_prepare ze znakiem ? w miejscu wartości, mysqli_stmt_bind_param z typem 'i' (liczba całkowita), mysqli_stmt_execute i mysqli_stmt_get_result - wynik czyta się dalej tą samą pętlą. Baza dostaje treść zapytania i wartość osobno, więc wartość nigdy nie stanie się kodem SQL. Podgląd: ta sama wartość z UNION - typ 'i' zamienia ją na liczbę 0 i blok środkowy jest pusty. Stara linia zostaje w komentarzu.
Typowe błędy
Liczba liter w 'i' musi równać się liczbie znaków ? i liczbie zmiennych - inaczej mysqli_stmt_bind_param zgłosi błąd.
Krok 40: Zabezpieczenie: sprawdzenie wartości z formularza
ok. 3 min
Polecenie z arkusza
Skrypt pobiera dane z pola edycyjnego
Dwie poprawki tego, co przychodzi z formularza:
(int) zamienia napis na liczbę całkowitą jeszcze przed nagłówkiem i zapytaniem: '4' daje 4, pusty napis i tekst w rodzaju 0 OR 1=1 - liczbę 0 lub inną liczbę, ale nigdy kod SQL. Puste pole przestaje wywracać stronę,
wartość spoza zakresu 1-5 dostaje komunikat „Wpisz numer gromady od 1 do 5.” - bez niego po wpisaniu 7 blok środkowy był po prostu pusty i nie było wiadomo dlaczego.
Podgląd: wartość 7 - komunikat zamiast pustego bloku. Arkusz tego komunikatu nie wymaga; na egzaminie nie przeszkadza w żadnym kryterium.
index.phpPHPzmienione: 5 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Dane o zwierzętach</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <h1>ATLAS ZWIERZĄT</h1> </header> <sectionid="form-block"> <h2>Gromady:</h2> <ol> <li>Ryby</li> <li>Płazy</li> <li>Gady</li> <li>Ptaki</li> <li>Ssaki</li> </ol> <formmethod="post"> Wybierz gromadę: <inputtype="number"name="gromada"> <inputtype="submit"value="Wyświetl"> </form> </section> <sectionid="left"> <imgsrc="zwierzeta.jpg"alt="dzikie zwierzęta"> </section> <sectionid="middle"><?php$connection = mysqli_connect('localhost', 'root', '', 'baza');if (isset($_POST['gromada'])) {// $gromada = $_POST['gromada'];$gromada = (int) $_POST['gromada'];if ($gromada < 1 || $gromada > 5) {echo'<p>Wpisz numer gromady od 1 do 5.</p>'; }if ($gromada == 1) {echo'<h2>RYBY</h2>'; } elseif ($gromada == 2) {echo'<h2>PŁAZY</h2>'; } elseif ($gromada == 3) {echo'<h2>GADY</h2>'; } elseif ($gromada == 4) {echo'<h2>PTAKI</h2>'; } elseif ($gromada == 5) {echo'<h2>SSAKI</h2>'; }// $result = mysqli_query($connection, "SELECT gatunek, wystepowanie FROM zwierzeta WHERE Gromady_id = $gromada;");$statement = mysqli_prepare($connection, 'SELECT gatunek, wystepowanie FROM zwierzeta WHERE Gromady_id = ?'); mysqli_stmt_bind_param($statement, 'i', $gromada); mysqli_stmt_execute($statement);$result = mysqli_stmt_get_result($statement);while ($row = mysqli_fetch_row($result)) {echo"$row[0], $row[1]<br>"; } }?> </section> <sectionid="right"> <h2>Wszystkie zwierzęta w bazie</h2><?php$result = mysqli_query($connection, 'SELECT zwierzeta.id, gatunek, nazwa FROM zwierzeta JOIN gromady ON zwierzeta.Gromady_id = gromady.id;');while ($row = mysqli_fetch_row($result)) {echo"$row[0]. $row[1], $row[2]<br>"; } mysqli_close($connection);?> </section> <footer> <ahref="https://atlas-zwierzat.pl"target="_blank">Poznaj inne strony o zwierzętach</a> autor Atlasu zwierząt: Bartosz Bryniarski </footer></body></html>
Podgląd strony po tym kroku (index.php)
Krok 41: Zabezpieczenie: htmlspecialchars na wyjściu
ok. 2 min
Polecenie z arkusza
W kolejnych wierszach wypisywane są rekordy w formacie: „<id>. <gatunek>, <nazwa gromady>”
Skrypty wypisują tekst z bazy prosto do HTML-a. Gdyby ktoś dopisał do tabeli gatunek w rodzaju <script>…</script> (np. przez inny formularz albo panel), przeglądarka wykonałaby go u każdego odwiedzającego - to atak XSS. Funkcja htmlspecialchars zamienia znaki <, >, & i cudzysłów na encje (< …), więc przeglądarka pokaże je jako tekst.
Zasada: dane wejściowe sprawdzasz przy odbiorze (poprzedni krok), a dane wypisywane - zabezpieczasz w chwili wypisywania. Liczby (id z bazy) tego nie potrzebują. Podgląd wygląda tak samo jak wcześniej - w danych z archiwum nie ma znaków specjalnych.
Krok 42 · po tym etapie masz 36 z 36 kryteriów (pkt)
Krok 42: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
UWAGA: po zakończeniu pracy utwórz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowałeś poprawność działania witryny. Umieść go w folderze z numerem zdającego.
W przeglądarka.txt wpisujesz nazwę przeglądarki, w której sprawdzasz stronę przez http://localhost/….
W folderze z numerem zdającego muszą być: import.png, index.php, kw1.jpg, kw2.jpg, kw3.jpg, kw4.jpg, kwerendy.txt, przeglądarka.txt, styl3.css i zwierzeta.jpg (plik baza2.sql z archiwum może zostać). Nagraj płytę, sprawdź jej odczyt i opisz ją numerem zdającego. Pusta lub nieczytelna płyta to zero punktów za wszystkie pięć rezultatów.
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.