Serwis używa plików cookies do analizy ruchu i poprawy działania. Szczegóły
EE.09-02-21.01-SGStyczeń 2021 · 43 kroki · ok. 85 min · 38 kryteriów z klucza
Rozwiązanie krok po kroku: Liga piłkarska i skład reprezentacji (Wersja podstawowa)
Strona o reprezentacji Polski i Lidze Mistrzów: baza egzamin zaimportowana z pliku, cztery zapytania (napastnicy, tabela ligi posortowana według punktów, złączenie zawodników z pozycjami i wyczyszczenie tabeli rozgrywka), grafika z piłką przeskalowana z zachowaniem przezroczystości, strona liga.php ze stylami w styl2.css oraz dwa skrypty PHP: pierwszy po wysłaniu formularza wypisuje zawodników z pozycji wybranej na liście rozwijalnej, drugi generuje z bazy bloki z drużynami ligi.
To arkusz EE.09 ze stycznia 2021 - kwalifikacji formuły 2017, którą zastąpiła INF.03. W tej samej sesji był arkusz EE.09-01-21.01 (rozgrywki futbolowe) na tej samej 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 napisane najprościej, funkcjami mysqli z tabeli 1 arkusza, a na końcu sprawdzone na prawdziwym wstrzyknięciu SQL i zabezpieczone.
To jest wersja podstawowa. W zakładce „Nowoczesny kod (flex, PDO)” jest drugi sposób rozwiązania tego samego arkusza: układ na display: flex, zmienne CSS, PDO z zapytaniem przygotowanym na górze pliku i wybrana pozycja zostająca na liście - obie wersje są zgodne z kluczem.
Baza i grafiki pochodzą z oryginalnego archiwum CKE z2.zip (załącznik do pobrania na stronie 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 od kroków z PHP to wynik prawdziwego uruchomienia kodu w PHP 8.2.
Jak liczą się punkty. Klucz ma 38 kryteriów (R.1.1 - R.5.9), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 29 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 38 kryteriów (pkt)
Krok 1: Folder zdającego i archiwum z2.zip
ok. 2 min
Polecenie z arkusza
Aby wykonać zadanie, zaloguj się na konto Egzamin bez hasła. Na pulpicie znajdziesz archiwum ZIP o nazwie z2.zip zabezpieczone hasłem: $piLkaRze% Archiwum należy rozpakować. Na pulpicie konta Egzamin utwórz folder. Jako nazwy folderu użyj swojego numeru PESEL. Umieść w tym folderze rozpakowane pliki. Po skończonej pracy wyniki zapisz również 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 z2.zip rozpakowujesz do tego folderu, podając hasło $piLkaRze% - wielkość liter ma znaczenie (wielkie są L i R). W środku są trzy pliki: egzamin.sql, obraz1.jpg (zdjęcie piłkarzy do banera) i zad2.png (sylwetka piłkarza z piłką na przezroczystym tle).
Typowe błędy
Pliki zapisane poza folderem zdającego nie trafią na płytę - a ocenia się tylko to, co jest na płycie.
Krok 2: XAMPP i pusta baza egzamin
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 bazę danych o nazwie egzamin
W XAMPP Control PanelStart przy Apache i MySQL, potem http://localhost/phpmyadmin, Nowa, nazwa egzamin, porównywanie np. utf8mb4_polish_ci, Utwórz.
Typowe błędy
Nazwa bazy musi brzmieć dokładnie egzamin - skrypt PHP łączy się z bazą po nazwie (R.5.2).
Krok 3: Import pliku egzamin.sql i zrzut import.png
Kryteria:
R.1.1 Wykonano import tabel do bazy danych egzamin , czynność udokumentowano plikiem o nazwie import w formacie PNG
ok. 3 min
Polecenie z arkusza
Do bazy egzamin zaimportuj plik egzamin.sql z rozpakowanego archiwum. Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w folderze z numerem PESEL, 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
Baza egzamin zaznaczona, karta Import, Wybierz plik → egzamin.sql, Wykonaj. Plik tworzy osiem tabel: cztery z obrazu 1 (liga, pozycja, rozgrywka, zawodnik) i cztery niepotrzebne w zadaniu. Zrzut całego ekranu z komunikatem o sukcesie i listą tabel zapisujesz jako import.png.
Typowe błędy
Zrzut importu ma format PNG, a zrzuty zapytań - JPG. Wykadrowany zrzut nie jest oceniany.
Podgląd strony po tym kroku
Krok 4: Zapytanie 1: napastnicy
Kryteria: ,
R.1.2 Zapisano plik tekstowy o nazwie kwerendy zawierający co najmniej jedno zapytanie SQL, wynikające z treści zadania
R.1.3 Utworzono zapytanie 1 wybierające jedynie pola imie i nazwisko z tabeli zawodnik dla zawodników, którym przypisano id pozycji równe 4 . W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = 4; oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczne są dokładnie 2 rekordy: Arkadiusz Milik, Adam Buksa
ok. 3 min
Polecenie z arkusza
Zapisz i wykonaj zapytania SQL działające na bazie egzamin. 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 imie i nazwisko z tabeli zawodnik dla zawodników, którym przypisane jest id pozycji równe 4
Karta SQL bazy egzamin:
SELECT imie, nazwisko - dwie kolumny („jedynie” wyklucza *),
FROM zawodnik,
WHERE pozycja_id = 4 - „id pozycji” to kolumna pozycja_id (klucz obcy do tabeli pozycja, 4 to napastnik).
Wynik: Arkadiusz Milik i Adam Buksa. Zapytanie trafia do kwerendy.txt, zrzut całego ekranu do kw1.jpg. Skrypt 1 użyje tego zapytania z numerem pozycji wybranym na liście.
Typowe błędy
WHERE id = 4 sprawdza identyfikator zawodnika, nie pozycję - wynikiem byłby tylko Grzegorz Krychowiak.
kwerendy.txtTekstnowy plik
-- Zapytanie 1SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = 4;
Podgląd strony po tym kroku
Krok 5: Zapytanie 2: tabela ligi według punktów
Kryteria:
R.1.4 Utworzono zapytanie 2 wybierające jedynie pola zespol, punkty, grupa z tabeli liga sortowane malejąco według punktów. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT zespol, punkty, grupa FROM liga ORDER BY punkty DESC; oraz wynik działania zapytania udokumentowano zrzutem, na którym widocznych jest dokładnie sześć rekordów: dla zespołów EVG, ARS, FCB, CHL, JUV, RM, jedynie kolumny zespol, punkty, grupa
ok. 2 min
Polecenie z arkusza
Zapytanie 2: wybierające jedynie pola zespol, punkty, grupa z tabeli liga sortowane malejąco według punktów
SELECT zespol, punkty, grupa FROM liga - trzy kolumny (tabela ma jeszcze id),
ORDER BY punkty DESC - sortowanie według punktów, DESC - malejąco (bez niego rosnąco, ASC).
Wynik: 6 drużyn od EVG (34) przez ARS, FCB, CHL i JUV do RM (5) - w tej kolejności stoją bloki na obrazie 2. Zrzut: kw2.jpg. To zapytanie wykona skrypt 2.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = 4;-- Zapytanie 2SELECT zespol, punkty, grupa FROM liga ORDER BY punkty DESC;
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: zawodnicy 3 i 5 z nazwą pozycji
Kryteria:
R.1.5 Utworzono zapytanie 3 wybierające jedynie pola id, nazwisko z tabeli zawodnik, oraz nazwę z tabeli pozycja dla zawodników, których id jest równe 3 lub 5. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT zawodnik.id, nazwisko, pozycja.nazwa FROM zawodnik JOIN pozycja ON zawodnik.pozycja_id = pozycja.id WHERE zawodnik.id=3 OR zawodnik.id=5; lub SELECT zawodnik.id, nazwisko, pozycja.nazwa FROM zawodnik, pozycja WHERE zawodnik.pozycja_id = pozycja.id AND (zawodnik.id=3 OR zawodnik.id=5); (nawias wymagany) oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczne są jedynie dwa rekordy, jedynie pola id, nazwisko, nazwa, dla id = 3 oraz id = 5
ok. 4 min
Polecenie z arkusza
Zapytanie 3: wybierające jedynie pola id, nazwisko z tabeli zawodnik oraz nazwę z tabeli pozycja dla zawodników, których id jest równe 3 lub 5
SELECT zawodnik.id, zawodnik.nazwisko, pozycja.nazwa - kolumna id jest w obu tabelach, więc trzeba wskazać tabelę (inaczej błąd #1052),
FROM zawodnik JOIN pozycja ON zawodnik.pozycja_id = pozycja.id - do zawodnika dołączana jest jego pozycja,
WHERE zawodnik.id = 3 OR zawodnik.id = 5 - „równe 3 lub 5” to dwa warunki połączone OR.
Wynik: 3 Bednarek obronca i 5 Grosicki pomocnik. Zrzut: kw3.jpg.
Typowe błędy
Wersja bez JOIN wymaga nawiasu: WHERE zawodnik.pozycja_id = pozycja.id AND (zawodnik.id = 3 OR zawodnik.id = 5). Bez nawiasu AND wiąże mocniej niż OR i zawodnik 5 połączy się z każdą z czterech pozycji - klucz zaznacza, że nawias jest wymagany.
kwerendy.txtTekstzmienione: 4 linie
-- Zapytanie 1SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = 4;-- Zapytanie 2SELECT zespol, punkty, grupa FROM liga ORDER BY punkty DESC;-- Zapytanie 3SELECT zawodnik.id, zawodnik.nazwisko, pozycja.nazwa FROM zawodnikJOIN pozycja ON zawodnik.pozycja_id = pozycja.id WHERE zawodnik.id = 3 OR zawodnik.id = 5;
R.1.6 Utworzono zapytanie 4 usuwające za pomocą jednej kwerendy SQL wszystkie dane z tabeli rozgrywka (sama tabela nie jest usuwana). W pliku z kwerendami lub na zrzucie istnieje zapis np.: TRUNCATE rozgrywka; lub DELETE FROM rozgrywka; oraz wynik działania zapytania udokumentowano zrzutem z widocznym poprawnym zapytaniem lub pustą tabelą rozgrywka
ok. 2 min
Polecenie z arkusza
Zapytanie 4: usuwające jedną kwerendą SQL wszystkie dane z tabeli rozgrywka (sama tabela nie jest usuwana)
TRUNCATE TABLE rozgrywka; usuwa wszystkie wiersze naraz, a tabela zostaje - pusta, z tą samą strukturą (licznik AUTO_INCREMENT też wraca do początku). Klucz przyjmuje też DELETE FROM rozgrywka; - bez WHERE usuwa wszystkie wiersze, jeden po drugim. phpMyAdmin pyta o potwierdzenie, a potem odpowiada „MySQL zwrócił pusty wynik”. Zrzut: kw4.jpg. Strona nie korzysta z tabeli rozgrywka, więc skryptom to nie przeszkadza.
Typowe błędy
DROP TABLE rozgrywka usuwa całą tabelę - a arkusz mówi wprost, że tabela ma zostać.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = 4;-- Zapytanie 2SELECT zespol, punkty, grupa FROM liga ORDER BY punkty DESC;-- Zapytanie 3SELECT zawodnik.id, zawodnik.nazwisko, pozycja.nazwa FROM zawodnikJOIN pozycja ON zawodnik.pozycja_id = pozycja.id WHERE zawodnik.id = 3 OR zawodnik.id = 5;-- Zapytanie 4TRUNCATE TABLE rozgrywka;
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 8-21 · po tym etapie masz 17 z 38 kryteriów (pkt)
Krok 8: Grafika zad2.png: szerokość 50 px z przezroczystością
Kryteria:
R.2.1 Plik zad2.png przeskalowano z zachowaniem proporcji do szerokości 50 px, odpowiadająca temu wysokość wynosi 71 px (± 5 px); przezroczystość została zachowana
ok. 2 min
Polecenie z arkusza
Plik zad2.png, wypakowany z archiwum, należy przeskalować z zachowaniem proporcji tak, aby jego szerokość wynosiła dokładnie 50 px. Należy zachować przezroczystość obrazu
Oryginał ma 414 × 589 px i przezroczyste tło. W GIMP-ie Obraz → Skaluj obraz, łańcuch zamknięty, szerokość 50 px - wysokość: 589 × 50 / 414 = 71,1, czyli 71 px (klucz: 71 px ±5). Eksport do PNG zachowuje kanał alfa.
Typowe błędy
Eksport do JPEG zamieni przezroczyste tło na jednolity kolor - klucz wymaga zachowania przezroczystości.
Podgląd strony po tym kroku
Krok 9: Plik liga.php
ok. 2 min
Polecenie z arkusza
Składa się ze strony o nazwie liga.php
Plik liga.php w folderze zdającego. Rozszerzenie .php, bo dojdą skrypty - na razie to czysty HTML. <!DOCTYPE html> oznacza HTML5, lang="pl" - język treści.
R.3.4 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl2.css , formatowanie 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 styl2.css prawidłowo połączony z kodem strony
<link rel="stylesheet" href="styl2.css"> - nazwa z cyfrą 2. Całe formatowanie trafi tylko do tego pliku (R.3.4).
Typowe błędy
href="styl.css" to brak stylów - plik nazywa się styl2.css. Klucz nie uznaje R.3.4 także przy źle przypisanym selektorze (kropka zamiast #).
Podział strony na bloki: baner, blok lewy i prawy, blok główny, blok liga zawierający zmienną liczbę bloków z informacją o drużynach. Bloki informacyjne generowane są skryptem, ich liczba zależy od liczby rekordów. Podział zrealizowany za pomocą znaczników sekcji, zgodnie z obrazem 2
Pięć znaczników <section> w kolejności z obrazu 2, z identyfikatorami banner, left, right, main i league (blok liga) - nazwy po angielsku, arkusz ich nie narzuca. Bloki z drużynami wygeneruje skrypt 2 wewnątrz league, po jednym <section> na drużynę. Na razie bloki stoją jeden pod drugim.
Krok 14: Baner: nagłówek trzeciego stopnia i zdjęcie
ok. 1 min
Polecenie z arkusza
Zawartość bloku banera: Nagłówek trzeciego stopnia o treści „Reprezentacja polski w piłce nożnej”. Obraz obraz1.jpg z tekstem alternatywnym o treści: „reprezentacja”
Trzeciego stopnia to <h3>. Tekst wpisujesz jak w arkuszu - „polski” małą literą (wielkie litery na początku słów doda CSS). Zdjęcie 930 × 272 px z tekstem alternatywnym.
liga.phpPHPzmienione: 2 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>piłka nożna</title> <linkrel="stylesheet"href="styl2.css"></head><body> <sectionid="banner"> <h3>Reprezentacja polski w piłce nożnej</h3> <imgsrc="obraz1.jpg"alt="reprezentacja"> </section> <sectionid="left"> </section> <sectionid="right"> </section> <sectionid="main"> </section> <sectionid="league"> </section></body></html>
Podgląd strony po tym kroku (liga.php)
Krok 15: Blok lewy: formularz wysyłający dane metodą POST
Kryteria: ,
R.2.7 W bloku lewym umieszczono formularz, zastosowano znacznik <form> oraz jego zamknięcie
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
Zawartość bloku lewego: Formularz wysyłający dane metodą POST do tej samej strony, zawierający:
<form method="post"> bez atrybutu action - dane wracają do liga.php, a w PHP odczytasz je z tablicy $_POST (R.2.7, R.3.3).
liga.phpPHPzmienione: 2 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>piłka nożna</title> <linkrel="stylesheet"href="styl2.css"></head><body> <sectionid="banner"> <h3>Reprezentacja polski w piłce nożnej</h3> <imgsrc="obraz1.jpg"alt="reprezentacja"> </section> <sectionid="left"> <formmethod="post"> </form> </section> <sectionid="right"> </section> <sectionid="main"> </section> <sectionid="league"> </section></body></html>
Podgląd strony po tym kroku (liga.php)
Krok 16: Lista rozwijalna z czterema pozycjami
ok. 2 min
Polecenie z arkusza
Listę rozwijalną z wpisami: Bramkarze, Obrońcy, Pomocnicy, Napastnicy
Lista rozwijalna to <select>, a każdy wpis to <option>. Tekst między znacznikami widzi użytkownik, a atrybut value trafia do PHP - tu numery 1-4, takie same jak id w tabeli pozycja (obraz 1). Dzięki temu skrypt wstawi wybraną wartość prosto do warunku pozycja_id = …. Nazwa listy: name="position".
Typowe błędy
Bez atrybutów value przeglądarka wyśle tekst wpisu („Pomocnicy”), a zapytanie WHERE pozycja_id = Pomocnicy zakończy się błędem.
liga.phpPHPzmienione: 6 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>piłka nożna</title> <linkrel="stylesheet"href="styl2.css"></head><body> <sectionid="banner"> <h3>Reprezentacja polski w piłce nożnej</h3> <imgsrc="obraz1.jpg"alt="reprezentacja"> </section> <sectionid="left"> <formmethod="post"> <selectname="position"> <optionvalue="1">Bramkarze</option> <optionvalue="2">Obrońcy</option> <optionvalue="3">Pomocnicy</option> <optionvalue="4">Napastnicy</option> </select> </form> </section> <sectionid="right"> </section> <sectionid="main"> </section> <sectionid="league"> </section></body></html>
Podgląd strony po tym kroku (liga.php)
Krok 17: Przycisk „Zobacz”
Kryteria: ,
R.2.8 W formularzu umieszczono listę rozwijalną z czterema elementami oraz przycisk "Zobacz"
R.3.2 Przycisk wysyła dane z formularza
ok. 1 min
Polecenie z arkusza
Przycisk wysyłający zawartość formularza z opisem „Zobacz”
<input type="submit" value="Zobacz"> - wysyła formularz (R.3.2). Lista z czterema wpisami i przycisk: R.2.8.
R.2.6 W bloku banera umieszczono obraz obraz1.jpg oraz w bloku lewym umieszczono obraz zad2.png. Przynajmniej jeden z obrazów ma tekst alternatywny: "reprezentacja" (dla obraz1.jpg ) lub "piłka" (dla zad2.png ) gdy obraz nie istnieje powinien wyświetlić się tekst alternatywny
ok. 1 min
Polecenie z arkusza
Obraz zad2.png z tekstem alternatywnym o treści: „piłka”
Przeskalowany zad2.png (50 × 71 px) pod formularzem. Oba obrazy strony mają tekst alternatywny (R.2.6).
Krok 20: Blok prawy: lista numerowana na wynik skryptu 1
Kryteria:
R.2.9 W bloku prawym umieszczono listę numerowaną, zapisano znaczniki <ol>, <li> oraz ich zamknięcia (generowaną skryptem lub HTML)
ok. 1 min
Polecenie z arkusza
Zawartość bloku prawego: Lista numerowana (uporządkowana) a w niej efekt działania skryptu 1
Lista uporządkowana to <ol> - numery 1, 2… dopisze przeglądarka. Elementy <li> wypisze skrypt 1, dlatego jego kod stanie między <ol> a </ol> (R.2.9 przyjmuje listę generowaną skryptem).
R.2.5 W bloku banera zapisano nagłówek h3: "Reprezentacja polski w piłce nożnej", w bloku głównym nagłówek h3: "Liga mistrzów" oraz zapisano paragraf z numerem PESEL
ok. 1 min
Polecenie z arkusza
Zawartość bloku głównego: nagłówek trzeciego stopnia o treści: „Liga mistrzów”. Zawartość bloku liga: Efekt działania skryptu 2
Drugi <h3>. Strona ma już oba nagłówki i paragraf z autorem (R.2.5). Blok liga zostaje pusty - wypełni go skrypt 2.
Kroki 22-31 · po tym etapie masz 28 z 38 kryteriów (pkt)
Krok 22: Plik styl2.css: krój i tło strony
Kryteria:
R.4.1 Ustawiono krój czcionki Verdana dla selektora body lub kontenera całej strony
ok. 1 min
Polecenie z arkusza
Dla znacznika body: krój czcionki Verdana, kolor tła SeaGreen
Nowy plik styl2.css. Selektor body: krój Verdana dziedziczą wszystkie elementy strony, SeaGreen to nazwa koloru CSS (morska zieleń) - R.4.1.
styl2.cssCSSnowy plik
body {font-family: Verdana;background-color: SeaGreen;}
Podgląd strony po tym kroku (liga.php)
Krok 23: Baner: biały tekst, wyśrodkowanie, wysokość
ok. 1 min
Polecenie z arkusza
Dla bloku banera: biały kolor czcionki, wyrównanie tekstu do środka, wysokość 330 px
Selektor identyfikatora #banner. text-align: center wyśrodkowuje nagłówek i zdjęcie, 330 px mieści nagłówek i zdjęcie wysokie na 272 px.
styl2.cssCSSzmienione: 5 linii
body {font-family: Verdana;background-color: SeaGreen;}#banner {color: white;text-align: center;height: 330px;}
Podgląd strony po tym kroku (liga.php)
Krok 24: Pojedynczy blok z drużyną: tekst, szerokość, marginesy
Kryteria:
R.4.7 Ustawiono dla pojedynczego bloku z informacją o drużynach marginesy zewnętrzne (margin) 5px, biały kolor czcionki, szerokość 170px, wyrównanie tekstu do środka
ok. 2 min
Polecenie z arkusza
Dla pojedynczego bloku z informacją o drużynach: biały kolor czcionki, wyrównanie tekstu do środka, szerokość 170 px, marginesy zewnętrzne 5 px
Bloki z drużynami to <section>wewnątrz bloku league, więc selektor potomny #league section - pięć głównych bloków strony go nie łapie. Bloków jeszcze nie ma: pojawią się ze skryptem 2, od razu w tym stylu (R.4.7).
Typowe błędy
Sam selektor section objąłby baner, blok lewy i prawy - wszystkie dostałyby szerokość 170 px.
Krok 25: Pojedynczy blok z drużyną: obramowanie i zaokrąglenie
Kryteria:
R.4.8 Ustawiono obramowanie o szerokości 1px linią ciągłą, białą oraz nadano zaokrąglenie rogów ramki 15px (border-radius) dla pojedynczego bloku z informacją o drużynach
Krok 26: Biały blok z czarnym tekstem po najechaniu kursorem
Kryteria:
R.4.9 W momencie najechania kursorem na pojedynczy blok z informacją o drużynach kolor jego tła zmienia się na biały, a czcionki na czarny (np. ustawiony kolor dla pseudoklasy hover lub inne rozwiązania)
ok. 1 min
Polecenie z arkusza
W momencie najechania kursorem na pojedynczy blok z informacją o drużynach, kolor tła zmienia się na biały a kolor czcionki na czarny
Pseudoklasa :hover - tło białe, tekst czarny, tylko gdy kursor jest nad blokiem; tak wygląda piąty blok (JUV) na obrazie 2 (R.4.9).
R.4.2 Ustawiono kolor tła SeaGreen dla selektora body lub kontenera całej strony oraz WhiteSmoke dla bloku lewego i prawego
R.4.4 Ustawiono wysokość banera na 330px, bloku lewego i prawego: 150px
R.4.5 Ustawiono szerokość bloku lewego na 30% i prawego na 70%
ok. 1 min
Polecenie z arkusza
Dla bloku prawego: kolor tła WhiteSmoke, szerokość 70%, wysokość 150 px
30% + 70% = 100% - oba bloki zmieszczą się obok siebie, jeśli nie dostaną marginesów ani ramek. Tła (R.4.2), wysokości banera i bloków (R.4.4) i szerokości (R.4.5) są ustawione.
Typowe błędy
padding albo border przy blokach 30% i 70% zepchną blok prawy pod lewy.
Krok 30: Nagłówki h3: wyśrodkowanie, odstęp liter, wielkie litery
Kryteria: ,
R.4.6 Ustawiono wyrównanie tekstu do środka dla banera, bloku lewego i selektora h3
R.4.10 Ustawiono styl selektora h3: odległość między literami 6px (letter-spacing) oraz kapitaliki (np. text-transform: capitalize; lub font-variant: small-caps;)
ok. 2 min
Polecenie z arkusza
Dla znacznika nagłówka trzeciego stopnia: wyrównanie tekstu do środka, odległość między literami 6 px, tekst napisany kapitalikami (capitalize)
text-align: center (razem z banerem i blokiem lewym: R.4.6), letter-spacing: 6px i text-transform: capitalize - wielka pierwsza litera każdego słowa: „Reprezentacja Polski W Piłce Nożnej”, jak na obrazie 2 (R.4.10).
⚠️ Uwaga o nazewnictwie: arkusz nazywa to „kapitalikami”, ale kapitaliki w typografii to font-variant: small-caps. Wartość w nawiasie i obraz 2 wskazują capitalize; klucz przyjmuje obie właściwości.
R.3.1 Widok układu bloków po uruchomieniu strony w przeglądarce jest w pełni zgodny z obrazem 2 w arkuszu egzaminacyjnym (nie należy brać pod uwagę bloków zawierających informacje o drużynach)
ok. 3 min
Polecenie z arkusza
Podział zrealizowany za pomocą znaczników sekcji, zgodnie z obrazem 2
#left, #right { float: left; } - blok lewy (30%) przy lewej krawędzi, prawy (70%) obok niego,
#main { clear: both; } - blok główny zaczyna się pod oboma pływającymi blokami,
#league section { float: left; } - bloki z drużynami w rzędzie (każdy zajmuje 170 + 2 + 2 × 5 = 182 px).
Klucz R.3.1 ocenia układ głównych bloków, bez bloków z drużynami. Podgląd: lewy i prawy blok obok siebie, nagłówek „Liga Mistrzów” pod nimi.
Typowe błędy
Bez clear: both nagłówek bloku głównego wjedzie w szare bloki lewy i prawy.
Kroki 32-39 · po tym etapie masz 38 z 38 kryteriów (pkt)
Krok 32: Miejsce skryptu 1 i połączenie z bazą egzamin
Kryteria: ,
R.5.1 Skrypt napisano w języku PHP oraz zawiera on co najmniej jedną instrukcję poprawną składniowo
R.5.2 Skrypt realizuje połączenie z serwerem bazy danych i wybór bazy egzamin
ok. 3 min
Polecenie z arkusza
Skrypt połączenia z bazą. Napisany w języku PHP, w pliku liga.php. Skrypt łączy się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie egzamin
Efekt skryptu 1 ma się pojawić w liście numerowanej w bloku prawym - tam więc, między <ol> a </ol>, piszesz pierwszy blok PHP. Pierwsza instrukcja: mysqli_connect z tabeli 1 - serwer localhost, użytkownik root, puste hasło '' i baza egzamin. Połączenie w zmiennej $connection posłuży też skryptowi 2, który stoi niżej w tym samym pliku (R.5.1, R.5.2).
Od tego kroku podgląd to wynik prawdziwego uruchomienia strony w PHP 8.2. Stronę sprawdzasz przez http://localhost/…/liga.php - przeglądarka sama nie wykona PHP.
R.5.4 W skrypcie działającym na danych przesłanych z formularza zastosowano tablicę $_POST, zapis musi być poprawny składniowo i logicznie
ok. 3 min
Polecenie z arkusza
Działanie skryptu 1, który odbiera dane przesłane z formularza: Odbiera dane z pola listy wyboru. Jeśli nic nie jest wybrane nie jest wykonywana żadna akcja
isset($_POST['position']) - prawdziwe dopiero po kliknięciu „Zobacz”. Przy pierwszym wejściu na stronę nic nie wybrano i skrypt nie robi nic,
$_POST['position'] - wartość value wybranego wpisu listy, czyli numer pozycji 1-4 (R.5.4).
Lista rozwijalna zawsze ma któryś wpis zaznaczony, więc „nic nie wybrano” oznacza tu „formularza nie wysłano”. Podgląd: wysłany wpis „Pomocnicy” (wartość 3) - lista jest jeszcze pusta.
R.5.5 Skrypt 1 wysyła do bazy danych zmodyfikowane zapytanie 1 tak, że w warunku id pozycji jest zgodne z wyborem w liście rozwijalnej lub Skrypt 2 wysyła do bazy zapytanie 2
ok. 2 min
Polecenie z arkusza
W innym przypadku skrypt wysyła do bazy danych zmodyfikowane zapytanie 1 tak, że w warunku id pozycji jest zgodne z wyborem w liście
Zapytanie 1 z kwerendy.txt, w którym zamiast 4 stoi $position. W cudzysłowie "…" PHP wstawia wartość zmiennej, a mysqli_query wysyła gotowe zapytanie do bazy i zwraca wynik do $result (R.5.5).
liga.phpPHPzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>piłka nożna</title> <linkrel="stylesheet"href="styl2.css"></head><body> <sectionid="banner"> <h3>Reprezentacja polski w piłce nożnej</h3> <imgsrc="obraz1.jpg"alt="reprezentacja"> </section> <sectionid="left"> <formmethod="post"> <selectname="position"> <optionvalue="1">Bramkarze</option> <optionvalue="2">Obrońcy</option> <optionvalue="3">Pomocnicy</option> <optionvalue="4">Napastnicy</option> </select> <inputtype="submit"value="Zobacz"> </form> <imgsrc="zad2.png"alt="piłka"> <p>Autor: Bartosz Bryniarski</p> </section> <sectionid="right"> <ol><?php$connection = mysqli_connect('localhost', 'root', '', 'egzamin');if (isset($_POST['position'])) {$position = $_POST['position'];$result = mysqli_query($connection, "SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = $position;");}?> </ol> </section> <sectionid="main"> <h3>Liga mistrzów</h3> </section> <sectionid="league"> </section></body></html>
Krok 35: Skrypt 1: imiona i nazwiska jako elementy listy
Kryteria:
R.5.6 Skrypt 1 wyświetla zwrócone zapytaniem imiona i nazwiska, które zostały przesłane przez formularz
ok. 3 min
Polecenie z arkusza
Wyświetla zwrócone zapytaniem dane: imiona i nazwiska w paragrafach, jako elementy listy numerowanej
Pętla while ($row = mysqli_fetch_row($result)) - kolejne wiersze jako tablice: $row[0] to imię, $row[1] nazwisko. Każdy zawodnik jako <li> z paragrafem <p> w środku.
Podgląd: wybrano Pomocnicy - lista pokazuje „1. Grzegorz Krychowiak” i „2. Kamil Grosicki”, jak na obrazie 2 (R.5.6). Lista rozwijalna po wysłaniu wraca do pierwszego wpisu, „Bramkarze” - też jak na obrazie 2: strona wczytuje się od nowa, a arkusz nie wymaga zapamiętania wyboru.
liga.phpPHPzmienione: 3 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>piłka nożna</title> <linkrel="stylesheet"href="styl2.css"></head><body> <sectionid="banner"> <h3>Reprezentacja polski w piłce nożnej</h3> <imgsrc="obraz1.jpg"alt="reprezentacja"> </section> <sectionid="left"> <formmethod="post"> <selectname="position"> <optionvalue="1">Bramkarze</option> <optionvalue="2">Obrońcy</option> <optionvalue="3">Pomocnicy</option> <optionvalue="4">Napastnicy</option> </select> <inputtype="submit"value="Zobacz"> </form> <imgsrc="zad2.png"alt="piłka"> <p>Autor: Bartosz Bryniarski</p> </section> <sectionid="right"> <ol><?php$connection = mysqli_connect('localhost', 'root', '', 'egzamin');if (isset($_POST['position'])) {$position = $_POST['position'];$result = mysqli_query($connection, "SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = $position;");while ($row = mysqli_fetch_row($result)) {echo"<li><p>$row[0]$row[1]</p></li>"; }}?> </ol> </section> <sectionid="main"> <h3>Liga mistrzów</h3> </section> <sectionid="league"> </section></body></html>
Podgląd strony po tym kroku (liga.php)
Krok 36: Skrypt 2: zapytanie 2 do bazy
ok. 2 min
Polecenie z arkusza
Działanie skryptu 2: Wysyła do bazy danych zapytanie 2
Drugi blok PHP w bloku league. mysqli_query wysyła zapytanie 2 z kwerendy.txt - tabela ligi posortowana malejąco według punktów - przez to samo połączenie $connection. Bloki pojawią się po dopisaniu pętli.
liga.phpPHPzmienione: 3 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>piłka nożna</title> <linkrel="stylesheet"href="styl2.css"></head><body> <sectionid="banner"> <h3>Reprezentacja polski w piłce nożnej</h3> <imgsrc="obraz1.jpg"alt="reprezentacja"> </section> <sectionid="left"> <formmethod="post"> <selectname="position"> <optionvalue="1">Bramkarze</option> <optionvalue="2">Obrońcy</option> <optionvalue="3">Pomocnicy</option> <optionvalue="4">Napastnicy</option> </select> <inputtype="submit"value="Zobacz"> </form> <imgsrc="zad2.png"alt="piłka"> <p>Autor: Bartosz Bryniarski</p> </section> <sectionid="right"> <ol><?php$connection = mysqli_connect('localhost', 'root', '', 'egzamin');if (isset($_POST['position'])) {$position = $_POST['position'];$result = mysqli_query($connection, "SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = $position;");while ($row = mysqli_fetch_row($result)) {echo"<li><p>$row[0]$row[1]</p></li>"; }}?> </ol> </section> <sectionid="main"> <h3>Liga mistrzów</h3> </section> <sectionid="league"><?php$result = mysqli_query($connection, 'SELECT zespol, punkty, grupa FROM liga ORDER BY punkty DESC;');?> </section></body></html>
Krok 37: Skrypt 2: blok sekcji z nazwą zespołu dla każdej drużyny
Kryteria: , ,
R.5.7 Skrypt 2 definiuje blok (za pomocą znacznika sekcji), a w nim wyświetla dane przesłane zapytaniem dotyczące jednego rekordu
R.5.9 Liczba wygenerowanych bloków odpowiada liczbie wierszy zwróconych zapytaniem
R.2.4 Wygląd strony zdefiniowano dzieląc ją na bloki: baner, blok lewy i prawy, blok główny, blok liga zawierający przynajmniej jeden blok z informacją o drużynach (w skrypcie lub HTML). Zastosowano znaczniki sekcji
ok. 4 min
Polecenie z arkusza
Definiuje blok (za pomocą znacznika sekcji), a w nim wyświetla dane przesłane zapytaniem dotyczące jednego rekordu: W nagłówku drugiego stopnia nazwę zespołu pobraną z bazy danych. Liczba wygenerowanych bloków odpowiada liczbie wierszy zwróconych zapytaniem
Pętla while z mysqli_fetch_row: w każdym obrocie echo '<section>', nagłówek <h2> z nazwą zespołu ($row[0]) i echo '</section>' - jeden blok na jeden wiersz wyniku, więc bloków jest tyle, ile drużyn w tabeli (R.5.7, R.5.9). Blok liga ma teraz bloki z informacją o drużynach (R.2.4).
Podgląd: sześć bloków od EVG do RM, od razu w ramkach i w rzędzie.
Typowe błędy
echo '<h2>$row[0]</h2>' w apostrofach wypisze dosłownie $row[0] - PHP podstawia zmienne tylko w cudzysłowie.
liga.phpPHPzmienione: 5 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>piłka nożna</title> <linkrel="stylesheet"href="styl2.css"></head><body> <sectionid="banner"> <h3>Reprezentacja polski w piłce nożnej</h3> <imgsrc="obraz1.jpg"alt="reprezentacja"> </section> <sectionid="left"> <formmethod="post"> <selectname="position"> <optionvalue="1">Bramkarze</option> <optionvalue="2">Obrońcy</option> <optionvalue="3">Pomocnicy</option> <optionvalue="4">Napastnicy</option> </select> <inputtype="submit"value="Zobacz"> </form> <imgsrc="zad2.png"alt="piłka"> <p>Autor: Bartosz Bryniarski</p> </section> <sectionid="right"> <ol><?php$connection = mysqli_connect('localhost', 'root', '', 'egzamin');if (isset($_POST['position'])) {$position = $_POST['position'];$result = mysqli_query($connection, "SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = $position;");while ($row = mysqli_fetch_row($result)) {echo"<li><p>$row[0]$row[1]</p></li>"; }}?> </ol> </section> <sectionid="main"> <h3>Liga mistrzów</h3> </section> <sectionid="league"><?php$result = mysqli_query($connection, 'SELECT zespol, punkty, grupa FROM liga ORDER BY punkty DESC;');while ($row = mysqli_fetch_row($result)) {echo'<section>';echo"<h2>$row[0]</h2>";echo'</section>';}?> </section></body></html>
Podgląd strony po tym kroku (liga.php)
Krok 38: Skrypt 2: punkty w h1 i grupa w paragrafie
Kryteria:
R.5.8 Skrypt 2 wyświetla dane wg wzoru: nazwa zespołu pobrana skryptem w h2, punkty pobrane skryptem w h1, w paragrafie tekst: „grupa: <grupa>”, gdzie <grupa> oznacza daną pobraną skryptem z bazy danych
ok. 2 min
Polecenie z arkusza
W nagłówku pierwszego stopnia punkty pobrane skryptem. W paragrafie tekst: „grupa: <grupa>”, gdzie <grupa> oznacza daną pobraną skryptem
Po nazwie zespołu <h1> z punktami ($row[1]) i paragraf „grupa: ” z literą grupy ($row[2]). Kolejność nagłówków jest nietypowa (h2 nad h1), ale tak każe arkusz i tak wygląda obraz 2 - punkty są największe (R.5.8).
liga.phpPHPzmienione: 2 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>piłka nożna</title> <linkrel="stylesheet"href="styl2.css"></head><body> <sectionid="banner"> <h3>Reprezentacja polski w piłce nożnej</h3> <imgsrc="obraz1.jpg"alt="reprezentacja"> </section> <sectionid="left"> <formmethod="post"> <selectname="position"> <optionvalue="1">Bramkarze</option> <optionvalue="2">Obrońcy</option> <optionvalue="3">Pomocnicy</option> <optionvalue="4">Napastnicy</option> </select> <inputtype="submit"value="Zobacz"> </form> <imgsrc="zad2.png"alt="piłka"> <p>Autor: Bartosz Bryniarski</p> </section> <sectionid="right"> <ol><?php$connection = mysqli_connect('localhost', 'root', '', 'egzamin');if (isset($_POST['position'])) {$position = $_POST['position'];$result = mysqli_query($connection, "SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = $position;");while ($row = mysqli_fetch_row($result)) {echo"<li><p>$row[0]$row[1]</p></li>"; }}?> </ol> </section> <sectionid="main"> <h3>Liga mistrzów</h3> </section> <sectionid="league"><?php$result = mysqli_query($connection, 'SELECT zespol, punkty, grupa FROM liga ORDER BY punkty DESC;');while ($row = mysqli_fetch_row($result)) {echo'<section>';echo"<h2>$row[0]</h2>";echo"<h1>$row[1]</h1>";echo"<p>grupa: $row[2]</p>";echo'</section>';}?> </section></body></html>
Podgląd strony po tym kroku (liga.php)
Krok 39: Zamknięcie połączenia z bazą
Kryteria:
R.5.3 Po wykonaniu operacji na bazie zastosowano funkcję zamknięcia bazy
ok. 1 min
Polecenie z arkusza
Po wykonaniu operacji na bazie danych skrypt zamyka połączenie z serwerem
mysqli_close($connection) na końcu drugiego bloku PHP - po ostatnim zapytaniu na stronie (R.5.3). Zamknięcie w bloku skryptu 1 odcięłoby skrypt 2 od bazy. Strona spełnia wszystkie kryteria arkusza; dalej trzy kroki o zabezpieczeniach - klucz ich nie wymaga.
liga.phpPHPzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>piłka nożna</title> <linkrel="stylesheet"href="styl2.css"></head><body> <sectionid="banner"> <h3>Reprezentacja polski w piłce nożnej</h3> <imgsrc="obraz1.jpg"alt="reprezentacja"> </section> <sectionid="left"> <formmethod="post"> <selectname="position"> <optionvalue="1">Bramkarze</option> <optionvalue="2">Obrońcy</option> <optionvalue="3">Pomocnicy</option> <optionvalue="4">Napastnicy</option> </select> <inputtype="submit"value="Zobacz"> </form> <imgsrc="zad2.png"alt="piłka"> <p>Autor: Bartosz Bryniarski</p> </section> <sectionid="right"> <ol><?php$connection = mysqli_connect('localhost', 'root', '', 'egzamin');if (isset($_POST['position'])) {$position = $_POST['position'];$result = mysqli_query($connection, "SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = $position;");while ($row = mysqli_fetch_row($result)) {echo"<li><p>$row[0]$row[1]</p></li>"; }}?> </ol> </section> <sectionid="main"> <h3>Liga mistrzów</h3> </section> <sectionid="league"><?php$result = mysqli_query($connection, 'SELECT zespol, punkty, grupa FROM liga ORDER BY punkty DESC;');while ($row = mysqli_fetch_row($result)) {echo'<section>';echo"<h2>$row[0]</h2>";echo"<h1>$row[1]</h1>";echo"<p>grupa: $row[2]</p>";echo'</section>';}mysqli_close($connection);?> </section></body></html>
Kroki 40-42 · po tym etapie masz 38 z 38 kryteriów (pkt)
Krok 40: Zabezpieczenie: zapytanie przygotowane w skrypcie 1
ok. 4 min
Polecenie z arkusza
W innym przypadku skrypt wysyła do bazy danych zmodyfikowane zapytanie 1 tak, że w warunku id pozycji jest zgodne z wyborem w liście
Lista rozwijalna podsuwa cztery wartości tylko w przeglądarce. Formularz można wysłać z pominięciem strony (programem curl albo po zmianie value w narzędziach deweloperskich), a wtedy w $_POST['position'] stoi dowolny tekst - i trafia wprost do zapytania. To SQL injection, sprawdzone na wersji z poprzednich kroków:
0 OR 1=1 - warunek zawsze prawdziwy, lista pokazuje wszystkich 7 zawodników,
0 UNION SELECT nazwa, cena FROM uslugi - do wyniku doklejają się wiersze z innej tabeli (dziesięć usług z cenami); tak samo dałoby się odczytać np. tabelę z hasłami,
abc - błąd składni SQL, PHP 8.1 i nowsze zgłaszają wyjątek mysqli_sql_exception i zamiast strony widać „Fatal error”.
Lekarstwo to zapytanie przygotowane: mysqli_prepare ze znakiem ? w miejscu numeru, mysqli_stmt_bind_param z typem 'i' (liczba całkowita), mysqli_stmt_execute i mysqli_stmt_get_result - dalej ta sama pętla. Baza dostaje zapytanie i dane osobno, więc dane nigdy nie staną się kodem SQL. Podgląd: atak z UNION - lista jest pusta. Stara linia zostaje w komentarzu.
Typowe błędy
Liczba liter w 'i' musi równać się liczbie znaków ? i liczbie zmiennych.
liga.phpPHPzmienione: 5 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>piłka nożna</title> <linkrel="stylesheet"href="styl2.css"></head><body> <sectionid="banner"> <h3>Reprezentacja polski w piłce nożnej</h3> <imgsrc="obraz1.jpg"alt="reprezentacja"> </section> <sectionid="left"> <formmethod="post"> <selectname="position"> <optionvalue="1">Bramkarze</option> <optionvalue="2">Obrońcy</option> <optionvalue="3">Pomocnicy</option> <optionvalue="4">Napastnicy</option> </select> <inputtype="submit"value="Zobacz"> </form> <imgsrc="zad2.png"alt="piłka"> <p>Autor: Bartosz Bryniarski</p> </section> <sectionid="right"> <ol><?php$connection = mysqli_connect('localhost', 'root', '', 'egzamin');if (isset($_POST['position'])) {$position = $_POST['position'];// $result = mysqli_query($connection, "SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = $position;");$statement = mysqli_prepare($connection, 'SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = ?;'); mysqli_stmt_bind_param($statement, 'i', $position); mysqli_stmt_execute($statement);$result = mysqli_stmt_get_result($statement);while ($row = mysqli_fetch_row($result)) {echo"<li><p>$row[0]$row[1]</p></li>"; }}?> </ol> </section> <sectionid="main"> <h3>Liga mistrzów</h3> </section> <sectionid="league"><?php$result = mysqli_query($connection, 'SELECT zespol, punkty, grupa FROM liga ORDER BY punkty DESC;');while ($row = mysqli_fetch_row($result)) {echo'<section>';echo"<h2>$row[0]</h2>";echo"<h1>$row[1]</h1>";echo"<p>grupa: $row[2]</p>";echo'</section>';}mysqli_close($connection);?> </section></body></html>
Podgląd strony po tym kroku (liga.php)
Krok 41: Zabezpieczenie: sprawdzenie numeru pozycji
ok. 3 min
Polecenie z arkusza
Odbiera dane z pola listy wyboru. Jeśli nic nie jest wybrane nie jest wykonywana żadna akcja
Lepiej odrzucić złe dane, zanim dojdzie do zapytania. filter_input(INPUT_POST, 'position', FILTER_VALIDATE_INT, …) zwraca liczbę tylko wtedy, gdy wysłany tekst jest liczbą całkowitą z zakresu 1-4 - dokładnie tych wartości, które stoją w <option>. W innym przypadku zwraca false, a gdy formularza nie wysłano - null; oba są fałszywe, więc if ($position) przepuszcza wyłącznie poprawne numery pozycji.
Podgląd: wysłana wartość 7, której na liście nie ma - zapytanie się nie wykonuje. Dwie stare linie zostają w komentarzu.
liga.phpPHPzmienione: 4 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>piłka nożna</title> <linkrel="stylesheet"href="styl2.css"></head><body> <sectionid="banner"> <h3>Reprezentacja polski w piłce nożnej</h3> <imgsrc="obraz1.jpg"alt="reprezentacja"> </section> <sectionid="left"> <formmethod="post"> <selectname="position"> <optionvalue="1">Bramkarze</option> <optionvalue="2">Obrońcy</option> <optionvalue="3">Pomocnicy</option> <optionvalue="4">Napastnicy</option> </select> <inputtype="submit"value="Zobacz"> </form> <imgsrc="zad2.png"alt="piłka"> <p>Autor: Bartosz Bryniarski</p> </section> <sectionid="right"> <ol><?php$connection = mysqli_connect('localhost', 'root', '', 'egzamin');// if (isset($_POST['position'])) {// $position = $_POST['position'];$position = filter_input(INPUT_POST, 'position', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 4]]);if ($position) {// $result = mysqli_query($connection, "SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = $position;");$statement = mysqli_prepare($connection, 'SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = ?;'); mysqli_stmt_bind_param($statement, 'i', $position); mysqli_stmt_execute($statement);$result = mysqli_stmt_get_result($statement);while ($row = mysqli_fetch_row($result)) {echo"<li><p>$row[0]$row[1]</p></li>"; }}?> </ol> </section> <sectionid="main"> <h3>Liga mistrzów</h3> </section> <sectionid="league"><?php$result = mysqli_query($connection, 'SELECT zespol, punkty, grupa FROM liga ORDER BY punkty DESC;');while ($row = mysqli_fetch_row($result)) {echo'<section>';echo"<h2>$row[0]</h2>";echo"<h1>$row[1]</h1>";echo"<p>grupa: $row[2]</p>";echo'</section>';}mysqli_close($connection);?> </section></body></html>
Krok 42: Zabezpieczenie: htmlspecialchars przy wypisywaniu danych
ok. 3 min
Polecenie z arkusza
Wyświetla zwrócone zapytaniem dane: imiona i nazwiska w paragrafach, jako elementy listy numerowanej
Oba skrypty wklejają w kod strony tekst prosto z bazy. Sprawdzone: po zmianie w tabeli liga nazwy drużyny RM na <i> (kolumna zespol mieści trzy znaki) wersja z poprzednich kroków wstawia do strony prawdziwy znacznik kursywy, który zostaje otwarty do końca strony - a w jego miejscu mógłby stać skrypt.
htmlspecialchars zamienia <, >, & i cudzysłowy na encje, więc przeglądarka pokaże je jako zwykłe znaki. array_map('htmlspecialchars', $row) zabezpiecza naraz wszystkie pola wiersza - w obu pętlach, tuż przed echo. Podgląd: strona jak na obrazie 2 - na zwykłych danych zmiana jest niewidoczna.
Na egzaminie wystarczy wersja wcześniejsza - klucz nie sprawdza żadnego z trzech zabezpieczeń.
liga.phpPHPzmienione: 2 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>piłka nożna</title> <linkrel="stylesheet"href="styl2.css"></head><body> <sectionid="banner"> <h3>Reprezentacja polski w piłce nożnej</h3> <imgsrc="obraz1.jpg"alt="reprezentacja"> </section> <sectionid="left"> <formmethod="post"> <selectname="position"> <optionvalue="1">Bramkarze</option> <optionvalue="2">Obrońcy</option> <optionvalue="3">Pomocnicy</option> <optionvalue="4">Napastnicy</option> </select> <inputtype="submit"value="Zobacz"> </form> <imgsrc="zad2.png"alt="piłka"> <p>Autor: Bartosz Bryniarski</p> </section> <sectionid="right"> <ol><?php$connection = mysqli_connect('localhost', 'root', '', 'egzamin');// if (isset($_POST['position'])) {// $position = $_POST['position'];$position = filter_input(INPUT_POST, 'position', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 4]]);if ($position) {// $result = mysqli_query($connection, "SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = $position;");$statement = mysqli_prepare($connection, 'SELECT imie, nazwisko FROM zawodnik WHERE pozycja_id = ?;'); mysqli_stmt_bind_param($statement, 'i', $position); mysqli_stmt_execute($statement);$result = mysqli_stmt_get_result($statement);while ($row = mysqli_fetch_row($result)) {$row = array_map('htmlspecialchars', $row);echo"<li><p>$row[0]$row[1]</p></li>"; }}?> </ol> </section> <sectionid="main"> <h3>Liga mistrzów</h3> </section> <sectionid="league"><?php$result = mysqli_query($connection, 'SELECT zespol, punkty, grupa FROM liga ORDER BY punkty DESC;');while ($row = mysqli_fetch_row($result)) {echo'<section>';$row = array_map('htmlspecialchars', $row);echo"<h2>$row[0]</h2>";echo"<h1>$row[1]</h1>";echo"<p>grupa: $row[2]</p>";echo'</section>';}mysqli_close($connection);?> </section></body></html>
Podgląd strony po tym kroku (liga.php)
Etap 6: Oddanie pracy
Krok 43 · po tym etapie masz 38 z 38 kryteriów (pkt)
Krok 43: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
Po zakończeniu pracy utwórz plik tekstowy. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowałeś poprawność działania witryny, zapisz go w folderze z numerem PESEL, jako przeglądarka.txt. Nagraj płytę z rezultatami pracy.
W przeglądarka.txt wpisujesz nazwę przeglądarki, w której sprawdzasz stronę przez http://localhost/….
W folderze z numerem PESEL muszą być: import.png, kw1.jpg, kw2.jpg, kw3.jpg, kw4.jpg, kwerendy.txt, liga.php, obraz1.jpg, przeglądarka.txt, styl2.css i zad2.png. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem PESEL. 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.