Serwis używa plików cookies do analizy ruchu i poprawy działania. Szczegóły
EE.09-01-22.01-SGStyczeń 2022 · 41 kroków · ok. 76 min · 31 kryteriów z klucza
Rozwiązanie krok po kroku: Zgłoszenie na kartę wędkarską (Wersja podstawowa)
Portal kart wędkarskich: baza wedkowanie z tabelami wędkarzy, łowisk i zawodów (import z pliku baza.sql), cztery zapytania - dopisanie wędkarza (INSERT), wybór wędkarzy z liczbą punktów powyżej 20, akwen łowiska wybrany przez relację z tabelą zawodów (JOIN) i utworzenie użytkownika bazy (CREATE USER). Do tego zdjęcie wędki przeskalowane do wysokości 220 px, strona karta.html z formularzem zgłoszenia, listą typów łowisk i odnośnikiem, style w styl_1.css oraz skrypt zapisz.php, który zapisuje dane z formularza w bazie.
To arkusz EE.09 ze stycznia 2022 - kwalifikacji formuły 2017, którą zastąpiła INF.03. 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 znaczniki, etykiety <label>, układ dolnych bloków w kontenerze flex, PDO z zapytaniem przygotowanym i sprawdzaniem danych - obie wersje są zgodne z kluczem.
Baza i zdjęcie pochodzą z oryginalnego archiwum CKE pliki1.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 skryptu to wynik prawdziwego uruchomienia kodu w PHP 8.2 (klucz każe sprawdzać w XAMPP 8.0.7 - użyte funkcje działają w obu wersjach tak samo).
Jak liczą się punkty. Klucz ma 31 kryteriów (R.1.1 - R.5.4), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 24 punkty (75% z 31 to 23,25, zaokrąglone w górę) - można stracić 7 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 31 kryteriów (pkt)
Krok 1: Folder zdającego i archiwum pliki1.zip
ok. 2 min
Polecenie z arkusza
Należy utworzyć folder o nazwie odpowiadającej numerowi PESEL zdającego lub w przypadku jego braku innemu numerowi, którym został podpisany arkusz. Archiwum należy rozpakować do tego folderu.
Na pulpicie tworzysz folder nazwany numerem PESEL - w tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora, Bartosz Bryniarski. Archiwum pliki1.zip rozpakowujesz do tego folderu, podając hasło K@RTY* (wielkie litery, małpa i gwiazdka mają znaczenie). W środku są dwa pliki: baza.sql (tabele do importu) i wedka.jpg (zdjęcie).
Do tego folderu trafia wszystko, co powstanie: zrzuty, kwerendy.txt, pliki strony, stylów i skryptu.
Typowe błędy
Pliki zapisane poza folderem zdającego (np. tylko w htdocs) nie trafią na płytę - a ocenia się tylko to, co jest na płycie.
Krok 2: XAMPP i baza wedkowanie
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 wedkowanie
W XAMPP Control Panel klikasz Start przy Apache i MySQL, potem w przeglądarce otwierasz http://localhost/phpmyadmin. Nowa w lewym panelu, nazwa wedkowanie (bez polskiej litery), porównywanie np. utf8mb4_polish_ci, Utwórz.
Typowe błędy
Nazwa bazy musi brzmieć dokładnie wedkowanie - skrypt łączy się z bazą po nazwie (R.5.1), a klucz sprawdza import do tej bazy (R.1.1).
Krok 3: Import pliku baza.sql i zrzut import.png
Kryteria:
R.1.1 Wykonano import tabel do bazy danych wedkowanie , czynność udokumentowano plikiem o nazwie import w formacie PNG. Zrzut zawiera cały obszar ekranu z widocznym paskiem zadań
ok. 3 min
Polecenie z arkusza
Do bazy wedkowanie zaimportuj tabele z pliku baza.sql z rozpakowanego archiwum. Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w folderze z numerem PESEL, lub w przypadku jego braku w folderze z innym numerem, którym został podpisany arkusz, 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ę wedkowanie, karta Import, Wybierz plik → baza.sql, Wykonaj. phpMyAdmin odpowiada zielonym komunikatem „Import zakończył się sukcesem”, a w lewym panelu pod bazą pojawia się lista tabel - w tym pliku jest ich 11, z czego zadanie używa trzech: karty_wedkarskie, lowisko i zawody_wedkarskie (reszta to tabele z innych zadań).
Zrzut całego ekranu z komunikatem i listą tabel zapisz jako import.png. Plik tworzy tabele z kodowaniem latin1 - zostaje tak, jak jest w archiwum.
Typowe błędy
Ten zrzut ma nazwę import i format PNG, zrzuty zapytań - JPEG. 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: karta Grzegorza Niemczyka
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 dodające rekord do tabeli karty_wedkarskie dla Grzegorza Niemczyka, adres="Gdynia, Batorego 14/5", z datą "2018-02-23", punkty=0. Baza powinna sama nadać wartość pola id dla tabeli. W pliku z kwerendami lub na zrzucie istnieje zapis np.: INSERT INTO `karty_wedkarskie` VALUES (NULL, 'Grzegorz', 'Niemczyk', 'Gdynia, Batorego 14/5', '2018-02-23', '0'); oraz wynik działania udokumentowano zrzutem, na którym widoczne jest poprawnie wykonane zapytanie lub tabela z dodanym rekordem
ok. 4 min
Polecenie z arkusza
Zapytanie 1: dodające rekord do tabeli Karty_wedkarskie dla Grzegorza Niemczyka, zamieszkałego pod adresem „Gdynia, Batorego 14/5”, z datą „2018-02-23”; wartość punktów: 0. Baza powinna sama nadać wartość pola id dla tabeli
Zaznacz bazę wedkowanie i otwórz kartę SQL. Zapytanie po kolei:
INSERT INTO karty_wedkarskie - do której tabeli; w bazie jej nazwa jest pisana małymi literami (w XAMPP na Windows wielkość liter w nazwach tabel nie ma znaczenia),
VALUES (NULL, ...) - wartości dla wszystkich sześciu kolumn w kolejności z tabeli: id, imie, nazwisko, adres, data_zezwolenia, punkty. NULL w kolumnie id z AUTO_INCREMENT oznacza „nadaj sam” - tak baza „sama nadaje wartość pola id”,
napisy i data w apostrofach, punkty jako liczba 0. Data w formacie RRRR-MM-DD - tak zapisuje ją typ DATE.
Wynik: „1 wiersz wstawiony”, nowy rekord ma id 3 (w tabeli były dwa). Zapytanie kopiujesz do pliku kwerendy.txt w folderze zdającego (R.1.2), a zrzut całego ekranu zapisujesz jako kw1.jpg - na zrzucie widać komunikat i tabelę z dodanym rekordem.
Typowe błędy
Bez listy kolumn trzeba podać wartość dla każdej kolumny - pominięcie NULL na początku daje błąd #1136 (liczba kolumn nie odpowiada liczbie wartości). Wpisanie konkretnego id, np. 3, odbiera punkt - arkusz każe nadać je bazie.
Krok 5: Zapytanie 2: wędkarze z liczbą punktów większą niż 20
Kryteria:
R.1.4 Utworzono zapytanie 2 wybierające jedynie pola imie i nazwisko z tabeli karty_wedkarskie dla wędkarzy, dla których liczba punktów jest większa niż 20. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, nazwisko FROM `karty_wedkarskie` WHERE punkty > 20; oraz wynik działania udokumentowano zrzutem, na którym widoczny jest dokładnie 1 rekord: Jan Kowalski; jedynie pola imie, nazwisko
ok. 2 min
Polecenie z arkusza
Zapytanie 2: wybierające jedynie pola imie i nazwisko z tabeli Karty_wedkarskie dla wędkarzy, dla których liczba punktów jest większa niż 20
SELECT imie, nazwisko - tylko dwie kolumny, „jedynie” wyklucza SELECT *,
FROM karty_wedkarskie,
WHERE punkty > 20 - „większa niż” to ostro większa, więc >, nie >=.
Wynik: dokładnie jeden wędkarz, Jan Kowalski (23 punkty) - tak jak w kluczu. Andrzej Nowak ma 3 punkty, a dodany przed chwilą Grzegorz Niemczyk 0. Zrzut: kw2.jpg.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1INSERT INTO karty_wedkarskie VALUES (NULL, 'Grzegorz', 'Niemczyk', 'Gdynia, Batorego 14/5', '2018-02-23', 0);-- Zapytanie 2SELECT imie, nazwisko FROM karty_wedkarskie WHERE punkty > 20;
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: akwen, gdzie sędzią jest Krzysztof Dobrowolski
Kryteria:
R.1.5 Utworzono zapytanie 3 wybierające jedynie pole akwen z tabeli lowisko dla łowisk, gdzie sędzią zawodów jest Krzysztof Dobrowolski. Zapytanie wykorzystuje relację. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT akwen FROM lowisko JOIN zawody_wedkarskie ON lowisko.id = zawody_wedkarskie.Lowisko_id WHERE sedzia= "Krzysztof Dobrowolski"; możliwe INNER JOIN lub SELECT akwen FROM lowisko, zawody_wedkarskie WHERE lowisko.id = zawody_wedkarskie.Lowisko_id AND sedzia= "Krzysztof Dobrowolski"; oraz wynik działania udokumentowano zrzutem, na którym widoczny jest dokładnie 1 rekord: Zalew Wegrowski; jedynie pole akwen
ok. 4 min
Polecenie z arkusza
Zapytanie 3: wybierające jedynie pole akwen z tabeli Lowisko dla łowisk, gdzie sędzią zawodów jest Krzysztof Dobrowolski, należy użyć relacji
Akwen jest w tabeli lowisko, a sędzia - w tabeli zawody_wedkarskie. Łączy je relacja: kolumna Lowisko_id w zawodach wskazuje id łowiska. Zapytanie klauzula po klauzuli:
SELECT akwen - jedyna kolumna z wyniku,
FROM lowisko JOIN zawody_wedkarskie - złączenie dwóch tabel,
ON lowisko.id = zawody_wedkarskie.Lowisko_id - warunek relacji; każdy wiersz zawodów zostaje połączony z łowiskiem, na którym się odbyły. Nazwy kolumn poprzedza nazwa tabeli, bo obie tabele mają kolumnę id,
WHERE sedzia = 'Krzysztof Dobrowolski' - tylko zawody tego sędziego.
Wynik: jeden akwen, Zalew Wegrowski (zgodnie z kluczem; w bazie nazwy są bez polskich liter). Zrzut: kw3.jpg. Klucz przyjmuje też starszy zapis z dwiema tabelami po przecinku i warunkiem relacji w WHERE - daje ten sam wynik.
Typowe błędy
Bez warunku ON (albo warunku relacji w WHERE) baza łączy każde łowisko z każdymi zawodami i ten sam sędzia „sędziuje” na wszystkich sześciu łowiskach.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1INSERT INTO karty_wedkarskie VALUES (NULL, 'Grzegorz', 'Niemczyk', 'Gdynia, Batorego 14/5', '2018-02-23', 0);-- Zapytanie 2SELECT imie, nazwisko FROM karty_wedkarskie WHERE punkty > 20;-- Zapytanie 3SELECT akwen FROM lowisko JOIN zawody_wedkarskie ON lowisko.id = zawody_wedkarskie.Lowisko_id WHERE sedzia = 'Krzysztof Dobrowolski';
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: użytkownik anna
Kryteria:
R.1.6 Utworzono zapytanie 4 tworzące użytkownika anna na localhost z hasłem anna123. W pliku z kwerendami lub na zrzucie istnieje zapis np.: CREATE USER "anna"@"localhost" IDENTIFIED BY "anna123"; oraz wynik działania udokumentowano zrzutem wskazującym na prawidłowo dodanego użytkownika
ok. 3 min
Polecenie z arkusza
Zapytanie 4: tworzące użytkownika anna na localhost z hasłem anna123
CREATE USER 'anna'@'localhost' - konto użytkownika serwera bazy; po małpie host, z którego może się logować („na localhost”),
IDENTIFIED BY 'anna123' - hasło. Baza nie przechowuje go wprost, tylko jego skrót.
Samo CREATE USER kończy się komunikatem „MySQL zwrócił pusty wynik”. Żeby zrzut kw4.jpg wskazywał na dodanego użytkownika, w tej samej karcie SQL dopisz pod spodem zapytanie sprawdzające SELECT User, Host, Password FROM mysql.user WHERE User = 'anna'; - phpMyAdmin pokaże wtedy wiersz z kontem anna@localhost i skrótem hasła *7E21CC99…. Konto widać też w zakładce Konta użytkowników. Do kwerendy.txt trafia tylko zapytanie 4.
Typowe błędy
Nazwa i host w osobnych apostrofach: 'anna'@'localhost'. Zapis 'anna@localhost' utworzy użytkownika o nazwie „anna@localhost” z dowolnego hosta.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1INSERT INTO karty_wedkarskie VALUES (NULL, 'Grzegorz', 'Niemczyk', 'Gdynia, Batorego 14/5', '2018-02-23', 0);-- Zapytanie 2SELECT imie, nazwisko FROM karty_wedkarskie WHERE punkty > 20;-- Zapytanie 3SELECT akwen FROM lowisko JOIN zawody_wedkarskie ON lowisko.id = zawody_wedkarskie.Lowisko_id WHERE sedzia = 'Krzysztof Dobrowolski';-- Zapytanie 4CREATE USER 'anna'@'localhost' IDENTIFIED BY 'anna123';
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 8-26 · po tym etapie masz 18 z 31 kryteriów (pkt)
Krok 8: Grafika: wysokość 220 px z zachowaniem proporcji
Kryteria:
R.2.1 Plik wedka.jpg przeskalowano z zachowaniem proporcji tak, że jego wysokość wynosi dokładnie 220 px, odpowiadająca temu szerokość wynosi 330 px ±5 px
ok. 2 min
Polecenie z arkusza
Plik wedka.jpg, wypakowany z archiwum, należy przeskalować z zachowaniem proporcji tak, aby jego wysokość wynosiła dokładnie 220 px
Oryginał ma 500 × 333 px. W GIMP-ie Obraz → Skaluj obraz, łańcuch między szerokością a wysokością zamknięty (to jest „zachowanie proporcji”), wysokość 220 px - szerokość przelicza się sama: 500 × 220 / 333 = 330,3, czyli 330 px (klucz: 330 px ±5). Zapis pod tą samą nazwą: Plik → Nadpisz wedka.jpg.
Typowe błędy
Wpisanie samej wysokości przy rozpiętym łańcuchu daje obraz 500 × 220 - spłaszczone zdjęcie i brak punktu. Zwykłe Zapisz w GIMP-ie zapisuje format .xcf, a nie JPEG.
Podgląd strony po tym kroku
Krok 9: Plik karta.html
ok. 1 min
Polecenie z arkusza
Składa się ze strony o nazwie karta.html oraz skryptu zapisz.php. Poniższe wymagania dotyczą tylko pliku karta.html
W edytorze tworzysz plik karta.html w folderze zdającego, obok wedka.jpg. To zwykła strona HTML - skrypt PHP będzie w osobnym pliku zapisz.php, do którego formularz wyśle dane. <!DOCTYPE html> oznacza HTML5, lang="pl" mówi przeglądarce i czytnikom ekranu, że treść jest po polsku.
R.2.2 Witrynę internetową zapisano w pliku karta.html oraz zastosowano 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 „wędkarską”, „łowisk” i „imię” mogą wyświetlić się jako krzaki. Plik trzeba też zapisać w UTF-8 (w Notepad++ menu Kodowanie). Nazwa pliku i kodowanie to razem jedno kryterium (R.2.2).
Tytuł strony widoczny na karcie przeglądarki: „Karty wędkarskie”
<title> w <head> - napis na karcie przeglądarki. Uwaga na podobne teksty: tytuł to „Karty wędkarskie”, nagłówek banera - „Zgłoszenie na kartę wędkarską”, a odnośnik - „Karta wędkarska”.
R.3.5 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl_1.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 styl_1.css prawidłowo połączony z kodem strony
<link rel="stylesheet" href="styl_1.css"> w <head>. W nazwie jest podkreślenie i cyfra: styl_1.css. Plik stylów powstanie po HTML-u.
Typowe błędy
Zła nazwa w href to strona bez stylów, a klucz uznaje R.3.5 tylko przy działającym połączeniu, w którym wszystkie selektory trafiają w bloki (kropka zamiast # też odbiera punkt).
R.2.4 Wygląd strony zdefiniowano dzieląc ją na bloki: baner, główny, trzy bloki: lewy, środkowy i prawy. Zastosowano znaczniki sekcji
ok. 2 min
Polecenie z arkusza
Podział strony na bloki: na górze blok banera, poniżej blok główny, na dole trzy bloki: lewy, środkowy i prawy. 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
Pięć bloków w kolejności z obrazu 2: baner <header>, a blok główny i trzy dolne jako <section>. Każda sekcja dostaje identyfikator, bo w CSS mają różne kolory i wymiary: main, left, middle i right (nazwy po angielsku - arkusz ich nie narzuca). Bloki są na razie puste i stoją jeden pod drugim; trzy dolne ustawi obok siebie CSS.
Zawartość bloku banera: nagłówek drugiego stopnia o treści „Zgłoszenie na kartę wędkarską”
Drugiego stopnia to <h2> - w tym arkuszu baner nie ma nagłówka <h1>. Klucz R.2.5 sprawdza go razem z nagłówkiem <h4> i paragrafem w bloku prawym - punkt przyjdzie po kroku z paragrafem.
Krok 16: Formularz wysyłający dane metodą POST do zapisz.php
Kryteria:
R.3.4 Formularz wysyła dane metodą POST do pliku zapisz.php
ok. 2 min
Polecenie z arkusza
Formularz wysyłający dane metodą POST do pliku zapisz.php zawierający pola
action="zapisz.php" - adres, pod który przeglądarka wyśle dane po kliknięciu przycisku wysyłającego,
method="post" - dane jadą w treści żądania, a nie w adresie strony; w PHP odczyta je tablica $_POST.
Formularz sprawdza się tylko przez serwer: stronę otwierasz jako http://localhost/…/karta.html, a nie dwuklikiem z dysku - inaczej przeglądarka pokaże kod zapisz.php zamiast go wykonać.
Typowe błędy
method="get" dopisze dane do adresu (zapisz.php?imie=...), a skrypt czytający $_POST nic nie dostanie.
„Podpisane powyżej” - napis, potem złamanie linii <br>, a pole w nowej linii, jak na obrazie 2. name="imie" (bez polskiej litery, tak jak kolumna w bazie) to klucz, pod którym wartość trafi do PHP - $_POST['imie']. Drugie <br> przenosi kolejny napis niżej.
Pole edycyjne podpisane powyżej tekstem: „adres: ”; pole ma rozmiar 30
Atrybut size="30" ustawia szerokość pola na około 30 znaków - dlatego na obrazie 2 pole adresu jest dłuższe niż pola imienia i nazwiska. Klucz przyjmuje też maxlength albo szerokość w CSS (R.2.8).
Typowe błędy
size zmienia tylko szerokość widoczną na ekranie, a maxlength - największą liczbę znaków, którą da się wpisać. Klucz przyjmuje oba, ale „rozmiar” pola to size.
Przycisk czyszczący zawartość formularza z etykietą „CZYŚĆ”
<input type="reset"> przywraca polom formularza wartości początkowe - tutaj puste. Napis na przycisku to value. Nie potrzeba do tego ani linijki JavaScriptu.
R.2.8 W bloku głównym umieszczono formularz z trzema polami edycyjnymi w tym pole do wpisania adresu ma rozmiar 30 (size lub maxlength lub width lub w CSS) oraz dwoma przyciskami "CZYŚĆ" i "ZAPISZ"
R.3.3 Pierwszy przycisk czyści zawartość formularza, drugi przycisk wysyła dane z formularza (input z typem submit lub button)
ok. 1 min
Polecenie z arkusza
Przycisk wysyłający zawartość formularza z etykietą „ZAPISZ”
<input type="submit"> wysyła formularz pod adres z action. Formularz jest kompletny: trzy pola edycyjne, w tym pole adresu o rozmiarze 30, i dwa przyciski (R.2.8); pierwszy czyści, drugi wysyła (R.3.3).
Typowe błędy
<input type="button"> wygląda tak samo, ale niczego nie wysyła - brak punktu R.3.3. Kolejność ma znaczenie: klucz mówi o pierwszym przycisku czyszczącym i drugim wysyłającym.
R.2.6 W bloku lewym umieszczono listę punktowaną (nieuporządkowaną) z czterema elementami: Zalewy, Stawy, Jeziora, Rzeki, zastosowano znaczniki <ul>, <li> oraz ich zamknięcia
ok. 1 min
Polecenie z arkusza
Lista punktowana (nieuporządkowana) zawierająca elementy: Zalewy, Stawy, Jeziora, Rzeki
Lista punktowana (nieuporządkowana) to <ul>, każdy element w <li>. Kropki dopisze przeglądarka (R.2.6).
Typowe błędy
<ol> to lista numerowana - klucz wymaga <ul> i <li> wraz z ich zamknięciami.
Krok 24: Blok środkowy: zdjęcie z tekstem alternatywnym
Kryteria:
R.2.7 W bloku środkowym umieszczono obraz wedka.jpg oraz ma on tekst alternatywny "karta wędkarska"
ok. 1 min
Polecenie z arkusza
Zawartość bloku środkowego: obraz wedka.jpg z tekstem alternatywnym o treści: „karta wędkarska”
<img> z atrybutami src (przeskalowany plik 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). Znacznik <img> w HTML5 nie ma znacznika zamykającego.
R.2.5 W banerze zapisano nagłówek h2: "Zgłoszenie na kartę wędkarską" oraz zapisano przynajmniej jeden nagłówek h4 z: "Formularz - karta wędkarska" w bloku głównym lub "Typy łowisk" w lewym oraz w bloku prawym paragraf z numerem PESEL lub innym numerem, którym został podpisany arkusz
ok. 1 min
Polecenie z arkusza
Zawartość bloku prawego: Akapit (paragraf) o treści: „Stronę przygotował: ”, dalej wstawiony numer PESEL zdającego lub w przypadku jego braku inny numer, którym został podpisany arkusz
Na egzaminie po dwukropku wpisujesz swój numer PESEL. W tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora: Bartosz Bryniarski. Tekst w znaczniku <p>. Strona ma teraz nagłówek <h2> w banerze, nagłówki <h4> w bloku głównym i lewym oraz paragraf w bloku prawym (R.2.5).
R.3.2 Wybranie odnośnika "Karta wędkarska" inicjuje otwarcie strony http://www.kartawedkarska.pl/
ok. 1 min
Polecenie z arkusza
Odnośnik do strony „http://www.kartawedkarska.pl/” o treści: „Karta wędkarska”
<a href="http://www.kartawedkarska.pl/"> - adres przepisany dokładnie z arkusza, z http:// na początku. Bez protokołu przeglądarka szukałaby pliku o takiej nazwie w folderze strony (R.3.2). Odnośnik stoi pod paragrafem, poza nim - na obrazie 2 to osobny prostokąt.
Kroki 27-33 · po tym etapie masz 27 z 31 kryteriów (pkt)
Krok 27: Plik styl_1.css: krój Georgia dla całej strony
Kryteria:
R.4.1 Ustawiono domyślny krój czcionki dla całej strony na Georgia (dla selektora * lub body lub html lub kontenera całej strony)
ok. 1 min
Polecenie z arkusza
Cechy formatowania CSS: Są zawarte wyłącznie w zewnętrznym arkuszu stylów. Domyślne dla całej strony: krój czcionki Georgia
Nowy plik styl_1.css w folderze zdającego - od teraz każda reguła trafia tylko tutaj, bez atrybutów style w HTML-u. Pierwsza reguła: selektor uniwersalny * z font-family: Georgia.
Dlaczego *, a nie body: pola formularza i przyciski nie dziedziczą kroju po body, a na obrazie 2 napisy „CZYŚĆ” i „ZAPISZ” są pisane krojem szeryfowym. Klucz R.4.1 przyjmuje oba selektory.
Dla bloku banera: kolor tła DodgerBlue, biały kolor czcionki, marginesy wewnętrzne 10 px, wyrównanie tekstu do środka
Selektor znacznika header - na stronie jest jeden baner. DodgerBlue i white to nazwy kolorów CSS, „marginesy wewnętrzne” to padding, a text-align: center wyśrodkowuje nagłówek.
Krok 29: Blok główny: tło LightBlue i marginesy wewnętrzne
Kryteria:
R.4.7 Ustawiono marginesy wewnętrzne (padding) dla banera na 10px i bloku głównego na 100px
ok. 1 min
Polecenie z arkusza
Dla bloku głównego: kolor tła LightBlue, marginesy wewnętrzne 100 px
Selektor identyfikatora #main - z krzyżykiem, bo w HTML-u jest id="main". padding: 100px odsuwa formularz od wszystkich czterech krawędzi bloku - stąd duży jasnoniebieski obszar na obrazie 2. Marginesy wewnętrzne banera i bloku głównego dają R.4.7.
R.4.2 Ustawiono kolor tła DodgerBlue dla banera i trzech bloków dolnych oraz kolor LightBlue dla bloku głównego
R.4.3 Ustawiono biały kolor czcionki dla banera i trzech bloków dolnych
R.4.4 Ustawiono wysokość trzech bloków dolnych na 220px
R.4.5 Ustawiono szerokość dolnych bloków: lewego na 20% oraz środkowego i prawego na 40%
R.4.6 Ustawiono wyrównanie tekstu do środka dla banera, bloku środkowego i prawego
ok. 2 min
Polecenie z arkusza
Wspólne dla bloku środkowego i bloku prawego: kolor tła DodgerBlue, biały kolor czcionki, szerokość 40%, wysokość 220 px, wyrównanie tekstu do środka
„Wspólne” - dwa selektory rozdzielone przecinkiem dostają jedną regułę. Teraz komplet kolorów tła (R.4.2), biały tekst banera i trzech dolnych bloków (R.4.3), wysokości 220 px (R.4.4), szerokości 20% + 40% + 40% = 100% (R.4.5) i wyśrodkowanie banera, bloku środkowego i prawego (R.4.6). text-align: center wyśrodkowuje też zdjęcie, bo <img> jest elementem w linii tekstu.
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 pozostałe.
Krok 32: Układ trzech dolnych bloków zgodny z obrazem 2
Kryteria:
R.3.1 Układ bloków po uruchomieniu strony 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. 2 min
Polecenie z arkusza
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
Trzy dolne bloki dostają float: left: blok lewy (20%) staje przy lewej krawędzi, środkowy (40%) obok niego, a prawy (40%) - obok środkowego. Razem mają dokładnie 100% szerokości, więc mieszczą się w jednym rzędzie. Baner i blok główny nie pływają - zajmują całą szerokość, jeden pod drugim.
Pod pływającymi blokami nie ma już żadnego elementu, więc clear nie jest potrzebne. Klucz R.3.1 przyjmuje float, flex albo grid; wersja nowoczesna pokazuje ten sam układ we flex.
Typowe błędy
float na samym bloku lewym nie wystarczy: środkowy blok jako zwykły blok zajmie całą szerokość pod nim, a prawy stanie jeszcze niżej.
Krok 33: Odnośnik: obramowanie kreskowane, tło i kolor tekstu
Kryteria:
R.4.8 Ustawiono styl odnośnika: obramowanie 1px dashed DimGray, kolor tła Gold, kolor czcionki DarkRed, marginesy wewnętrzne 10px (selektor a lub klasa lub identyfikator)
ok. 2 min
Polecenie z arkusza
Dla znacznika odnośnika: obramowanie linią kreskowaną o szerokości 1 px i kolorze DimGray, kolor tła Gold, kolor czcionki DarkRed, marginesy wewnętrzne 10 px
Selektor znacznika a. Skrót border: 1px dashed DimGray - szerokość, styl linii (dashed - kreskowana, dotted - kropkowana, solid - ciągła) i kolor w jednej właściwości. Złoty prostokąt z ciemnoczerwonym napisem, jak na obrazie 2 (R.4.8). Arkusz stylów jest kompletny.
Typowe błędy
dotted to linia z kropek, a arkusz chce kreskowanej - dashed.
Kroki 34-37 · po tym etapie masz 31 z 31 kryteriów (pkt)
Krok 34: Plik zapisz.php i połączenie z bazą wedkowanie
Kryteria:
R.5.1 Skrypt realizuje połączenie z serwerem bazy danych i wybór bazy wedkowanie
ok. 3 min
Polecenie z arkusza
Skrypt połączenia z bazą. Napisany w języku PHP, w pliku zapisz.php. Skrypt łączy się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie wedkowanie
Nowy plik zapisz.php w folderze zdającego - ten sam, który wskazuje action formularza. Cały plik to skrypt między <?php a ?>.
Pierwsza instrukcja: mysqli_connect z tabeli 1 arkusza - kolejno serwer localhost, użytkownik root, puste hasło '' i nazwa bazy wedkowanie. Połączenie trafia do zmiennej $connection, z której skorzystają kolejne funkcje (R.5.1).
Skrypt niczego nie wypisuje - arkusz nie każe pokazywać żadnego komunikatu - więc po wysłaniu formularza przeglądarka pokaże pustą stronę. Efekt widać w bazie. Dlatego podgląd w krokach skryptu pokazuje formularz z karta.html, a od kroku z zapytaniem - tabelę w phpMyAdmin po wysłaniu formularza.
R.5.3 Skrypt pobiera dane z formularza za pomocą tablicy $_POST (lub $_REQUEST gdy sprawdzono, że REQUEST_METHOD jest równe POST)
ok. 2 min
Polecenie z arkusza
Skrypt działa na danych przesłanych z formularza
Trzy wartości z formularza trafiają do zmiennych o tych samych nazwach. Kluczem w $_POST jest atrybut name pola: $_POST['imie'], $_POST['nazwisko'], $_POST['adres'] (R.5.3). Tablica $_POST istnieje, bo formularz ma method="post".
Typowe błędy
Nazwa w nawiasie musi być identyczna z name w HTML-u: $_POST['imię'] (z „ę”) albo $_POST['Imie'] nie znajdzie pola i PHP zgłosi ostrzeżenie „Undefined array key”.
Krok 36: Zmodyfikowane zapytanie 1 z danymi z formularza
Kryteria:
R.5.4 Skrypt wysyła do bazy danych zapytanie 1 wstawiające dane do bazy: pola data_zezwolenia i punkty = NULL, pozostałe wartości wypełnione są danymi z formularza. Należy sprawdzić w bazie czy rekord został dodany
ok. 3 min
Polecenie z arkusza
Skrypt wysyła do bazy danych zmodyfikowane zapytanie 1, które w polach data_zezwolenia i punkty zawiera wartość NULL, pozostałe wartości wypełnione są danymi z formularza
Zapytanie 1 z kwerendy.txt z trzema zmianami: w miejsce 'Grzegorz', 'Niemczyk' i adresu stoją zmienne '$imie', '$nazwisko', '$adres', a w miejsce daty i punktów - NULL (bez apostrofów, bo to „brak wartości”, a nie napis). Pierwsze NULL zostaje: id nadaje baza. Całe zapytanie jest w cudzysłowie "…", więc PHP podstawia wartości zmiennych, a apostrofy w środku są ogranicznikami napisów w SQL.
Sprawdzenie, jak każe klucz (R.5.4): formularz z danymi Marek, Lis, „Sopot, Morska 3” i w phpMyAdmin nowy wiersz 3 z NULL w kolumnach data_zezwolenia i punkty - podgląd pokazuje tabelę po wysłaniu.
Typowe błędy
'NULL' w apostrofach to napis: w kolumnie DATE zamieni się na „0000-00-00” albo zgłosi błąd, zamiast zostawić puste pole. Zapytanie w apostrofach 'INSERT ... '$imie' ...' - PHP nie podstawi zmiennych.
Tabela z archiwum ma kodowanie latin1, które nie zna liter ą, ć, ę, ł, ń, ś, ź, ż - dane Łukasz Żółć, Gdańsk zapisały się jako „?ukasz ?ó??, Gda?sk”. To nie jest błąd skryptu i nie traci się za to punktu: klucz sprawdza import pliku bez zmian, więc kodowania tabeli nie zmieniasz.
R.5.2 Ostatnią operacją na bazie jest jej zamknięcie (zgodne ze składnią)
ok. 1 min
Polecenie z arkusza
Na końcu działania skrypt zamyka połączenie z serwerem.
mysqli_close($connection) jako ostatnia instrukcja skryptu - po zapytaniu (R.5.2). Skrypt spełnia wszystkie kryteria arkusza. Dalej trzy kroki o zabezpieczeniach - klucz ich nie wymaga.
Typowe błędy
mysqli_close przed mysqli_query sprawia, że zapytanie dostaje zamknięte połączenie i PHP kończy się błędem - a klucz wymaga, by zamknięcie było ostatnią operacją na bazie.
Kroki 38-40 · po tym etapie masz 31 z 31 kryteriów (pkt)
Krok 38: Zabezpieczenie: zapytanie przygotowane
ok. 4 min
Polecenie z arkusza
Skrypt wysyła do bazy danych zmodyfikowane zapytanie 1, które w polach data_zezwolenia i punkty zawiera wartość NULL, pozostałe wartości wypełnione są danymi z formularza
Dane z formularza trafiają do zapytania wprost - to SQL injection. Sprawdzone na wersji z poprzednich kroków:
w pole adresu wpisano x', NULL, NULL), (NULL, 'Jan', 'Mistrz', 'Gdynia', '2018-01-01', 999) -- - apostrof kończy napis, a reszta staje się kodem SQL. Do tabeli trafiły dwa rekordy, w tym wymyślony wędkarz z 999 punktami i datą zezwolenia, choć formularz w ogóle nie ma takich pól - zapytanie 2 pokazuje go teraz obok Jana Kowalskiego,
nazwisko z apostrofem, np. O'Brien, rozbija składnię - 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 znakami ? w miejscu danych, mysqli_stmt_bind_param z typami 'sss' (trzy napisy) i mysqli_stmt_execute. Baza dostaje treść zapytania i dane osobno, więc dane nigdy nie staną się kodem SQL. Podgląd: ten sam „adres-atak” zapisuje się jako zwykły, dziwny adres jednej osoby, a O'Brien zapisuje się bez błędu. Stara linia zostaje w komentarzu. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
Typowe błędy
Liczba liter w 'sss' musi równać się liczbie znaków ? i liczbie zmiennych - inaczej mysqli_stmt_bind_param zgłosi błąd i rekord nie powstanie.
Krok 39: Zabezpieczenie: sprawdzenie danych przed zapisem
ok. 4 min
Polecenie z arkusza
Skrypt działa na danych przesłanych z formularza
Dwa przypadki, które w wersji egzaminacyjnej zapisują do bazy śmieci - oba sprawdzone:
wejście na zapisz.php bez formularza (np. z historii przeglądarki albo przez robota) - tablica $_POST jest pusta, PHP wypisuje trzy ostrzeżenia „Undefined array key”, a do tabeli trafia rekord z pustym imieniem, nazwiskiem i adresem. Teraz skrypt sprawdza $_SERVER['REQUEST_METHOD'] i każde wejście inne niż POST przekierowuje z powrotem do formularza (header('Location: …') z exit),
puste pola - formularz można wysłać bez wpisania czegokolwiek. trim() zdejmuje spacje z brzegów (pole z samą spacją też jest puste), ?? '' chroni przed brakującym kluczem, a gdy któreś pole jest puste, exit kończy skrypt komunikatem, zanim cokolwiek trafi do bazy.
htmlspecialchars nie jest tu potrzebny: skrypt nie wypisuje niczego, co wpisał użytkownik. Gdyby wypisywał (np. „Zapisano kartę dla Marka Lisa”), dane trzeba przepuścić przez htmlspecialchars przed echo - pokazuje to wersja nowoczesna.
Typowe błędy
Bez exit po header(...) skrypt działa dalej i zapisuje rekord - przekierowanie to tylko nagłówek odpowiedzi.
Zapytanie 4: tworzące użytkownika anna na localhost z hasłem anna123
Dwie rzeczy, które na egzaminie są w porządku, a w prawdziwym serwisie nie:
skrypt łączy się jako root bez hasła - administrator całego serwera baz danych. W XAMPP do nauki tak jest domyślnie, a arkusz tego wymaga (R.5.1). Na serwerze strona łączy się kontem z prawami tylko do swojej bazy (np. GRANT SELECT, INSERT ON wedkowanie.karty_wedkarskie TO …), z długim losowym hasłem,
hasło anna123 z zapytania 4 jest do ćwiczeń - słowo i trzy kolejne cyfry odgaduje się w ułamku sekundy ze słownika popularnych haseł.
Do pliku egzaminacyjnego nic z tego nie przenosisz - zapytanie 4 i połączenie zostają takie, jak każe arkusz. Plik skryptu bez zmian.
Krok 41 · po tym etapie masz 31 z 31 kryteriów (pkt)
Krok 41: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
UWAGA: po zakończeniu pracy utwórz w folderze z numerem PESEL lub w przypadku jego braku w folderze z innym numerem, którym został podpisany arkusz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowano poprawność działania witryny. 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 zdającego muszą być: import.png, karta.html, kw1.jpg, kw2.jpg, kw3.jpg, kw4.jpg, kwerendy.txt, przeglądarka.txt, styl_1.css, wedka.jpg i zapisz.php (plik baza.sql z archiwum może zostać). Nagraj płytę, sprawdź jej odczyt w obecności przewodniczącego zespołu nadzorującego i opisz ją numerem zdającego. Pusta lub nieczytelna płyta to zero punktów za wszystkie pięć rezultatów.
przeglądarka.txtTekstnowy plik
Google Chrome
Podgląd strony po tym kroku (karta.html)
Podgląd
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.