INF.03-05-23.01-SGStyczeń 2023 · 40 kroków · ok. 70 min · 34 kryteria z klucza
Rozwiązanie krok po kroku: Internetowy kalendarz sierpniowy (Wersja podstawowa)
Kalendarz sierpniowy to baza kalendarz z jedną tabelą zadania (dzień, wpis, nazwa miesiąca, rok), cztery zapytania - warunek na tekście, warunek na dacie, liczenie z grupowaniem (COUNT + GROUP BY) i UPDATE - oraz jedna strona organizer.php. Strona ma dwa skrypty: Skrypt 1 rysuje kalendarz - dla każdego dnia sierpnia osobny blok z datą i wpisem - a skrypt obsługujący formularz zapisuje wpisany tekst do dnia 9 sierpnia, czyli wykonuje zapytanie 4 z wartością z formularza. W stylach jest :hover na bloku kalendarza i dwie reguły, które klucz każe pisać selektorem znacznika (h5 i form), a nie klasą.
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 z tabeli 1 arkusza (mysqli_query, mysqli_fetch_row), a na końcu przerobione na wersję odporną na błędy, które naprawdę wychodzą przy testach.
To jest wersja podstawowa. W zakładce „Nowoczesny kod (grid, flex, PDO)” jest drugi sposób rozwiązania tego samego arkusza: trzy bloki banera w siatce CSS wewnątrz jednego znacznika <header>, bloki kalendarza ułożone flexboksem, zapis przez PDO zapytaniem przygotowanym z przekierowaniem po zapisie (wzorzec PRG) i bezpieczne wypisywanie wpisów - obie wersje są zgodne z kluczem.
Baza i logo pochodzą z prawdziwego archiwum zad5.zip (załącznik do arkusza, hasło w treści zadania). Zapytania i zrzuty są policzone na MariaDB 10.4 - tej samej, która jest w XAMPP. Podgląd strony od kroków z PHP to wynik prawdziwego uruchomienia kodu w PHP 8.2 (klucz każe sprawdzać w XAMPP 8.1.2 - zachowanie użytych funkcji jest w obu wersjach takie samo); od kroków Skryptu 1 podgląd pokazuje stronę po wysłaniu formularza z wpisem „zakupy”, jak na obrazie 2.
Jak liczą się punkty. Klucz ma 34 kryteria (R.1.1 - R.5.7), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 26 punktów - można stracić 8 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 34 kryteriów (pkt)
Krok 1: Baza danych kalendarz
ok. 2 min
Polecenie z arkusza
Utwórz bazę danych o nazwie kalendarz
Najpierw archiwum zad5.zip z pulpitu (hasło kaL(end)arz% - z nawiasami w środku i procentem na końcu) i folder z numerem zdającego, do którego trafiają baza5.sql, logo1.png i logo2.png. W phpMyAdmin: Nowa, nazwa kalendarz - plik SQL nazywa się inaczej niż baza.
Typowe błędy
Nazwa bazy musi brzmieć dokładnie kalendarz (nie baza5 ani egzamin z komentarza w pliku) - skrypt łączy się z bazą po nazwie (R.5.1).
Krok 2: Import tabeli z pliku baza5.sql
ok. 2 min
Polecenie z arkusza
Do bazy kalendarz zaimportuj tabele z pliku baza5.sql z rozpakowanego archiwum
Przy zaznaczonej bazie kalendarz: Import → baza5.sql → Wykonaj. Powstaje tabela zadania z obrazu 1: 63 dni - cały lipiec i cały sierpień 2020 roku oraz jeden dzień listopada. Pole miesiac zawiera nazwę miesiąca bez polskich liter (sierpien), a pole wpis dla dni bez zadań ma pusty tekst; tylko listopadowy wiersz ma w nim NULL.
Krok 3: Zrzut ekranu import.png
Kryteria:
R.1.1 Wykonano import tabel do bazy danych kalendarz czynność udokumentowano plikiem o nazwie import w formacie PNG
ok. 2 min
Polecenie z arkusza
Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w formacie PNG pod nazwą import. Nie kadruj zrzutu. Zrzut powinien obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel
Print Screen, wklejenie do edytora grafiki i zapis jako import.png. Uwaga na formaty: import idzie do PNG, a zrzuty zapytań do JPEG.
Typowe błędy
Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).
Krok 4: Zapytanie 1: zadania z sierpnia
Kryteria: ,
R.1.2 Zapisano plik kwerendy.txt zawierający co najmniej jedno zapytanie SQL, wynikające z treści zadania
R.1.3 Utworzono zapytanie 1 wybierające jedynie pola dataZadania i wpis dla zadań z sierpnia. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT dataZadania, wpis FROM zadania WHERE miesiac = 'sierpien'; (poprawne też: dataZadania LIKE '____-08-__' lub użycie %) oraz wynik działania udokumentowano zrzutem, na którym widoczny jest w komunikacie zapis o liczbie rekordów "(31 ogółem...)", rekordy są jedynie z sierpnia, jedynie pola dataZadania i wpis. Na zrzucie nie muszą być widoczne wszystkie zwrócone zapytaniem wiersze
ok. 2 min
Polecenie z arkusza
Zapytanie 1: wybierające jedynie pola dataZadania i wpis dla zadań, z miesiąca sierpnia
SELECT dataZadania, wpis - dwa pola, nazwa dataZadania z wielką literą w środku,
FROM zadania,
WHERE miesiac = 'sierpien' - tekst w bazie jest bez polskich liter, więc 'sierpień' nie znalazłoby nic.
Wynik: 31 wierszy (komunikat „31 ogółem”), od 2020-08-01 Remont do 2020-08-31. Klucz uznaje też warunek na dacie, np. dataZadania LIKE '____-08-__' - daje te same 31 dni (sprawdzone). Z tego zapytania powstanie Skrypt 1. Zapytania trafiają do kwerendy.txt, zrzut wyniku do kw1.jpg.
kwerendy.txtTekstnowy plik
-- Zapytanie 1SELECT dataZadania, wpis FROM zadania WHERE miesiac = 'sierpien';
Podgląd strony po tym kroku
Krok 5: Zapytanie 2: miesiąc i rok dla 7 sierpnia 2020
Kryteria:
R.1.4 Utworzono zapytanie 2 wybierające jedynie pola miesiac i rok dla zadania z dnia 7 sierpnia 2020 r. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT miesiac, rok FROM zadania WHERE dataZadania = '2020-08- 07'; oraz wynik działania udokumentowano zrzutem, na którym widoczne jest: sierpien, 2020
ok. 1 min
Polecenie z arkusza
Zapytanie 2: wybierające jedynie pola miesiac i rok dla zadania z dnia 7 sierpnia 2020 r.
SELECT miesiac, rok,
FROM zadania,
WHERE dataZadania = '2020-08-07' - data w zapytaniu SQL ma postać rok-miesiąc-dzień w apostrofach.
Wynik: jeden wiersz sierpien, 2020 - jak w kluczu. Zrzut: kw2.jpg.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT dataZadania, wpis FROM zadania WHERE miesiac = 'sierpien';-- Zapytanie 2SELECT miesiac, rok FROM zadania WHERE dataZadania = '2020-08-07';
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: wizyty u weterynarza w każdym miesiącu
Kryteria:
R.1.5 Utworzono zapytanie 3 wybierające jedynie nazwę miesiąca oraz w kolumnie wpis zliczające dla każdego miesiąca wpisy rozpoczynające się od słowa „Weterynarz”. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT miesiac, COUNT(*) FROM zadania WHERE wpis LIKE 'Weterynarz%' GROUP BY miesiac; (zamiast * może być dowolne pole) oraz wynik działania udokumentowano zrzutem, na którym widoczne jest jedynie: lipiec, 2; sierpien, 2
ok. 2 min
Polecenie z arkusza
Zapytanie 3: wybierające jedynie nazwę miesiąca oraz liczące dla każdego miesiąca ile jest wpisów rozpoczynających się od słowa „Weterynarz” w kolumnie wpis
SELECT miesiac, COUNT(*) - nazwa miesiąca i liczba wierszy,
FROM zadania,
WHERE wpis LIKE 'Weterynarz%' - % zastępuje dowolny ciąg znaków, więc pasują wpisy „Weterynarz - Brutus” i „Weterynarz - Dika”; znak tylko na końcu wzorca oznacza „rozpoczyna się od”,
GROUP BY miesiac - COUNT liczy osobno dla każdego miesiąca.
Wynik: lipiec 2 i sierpien 2 - jak w kluczu. Listopad nie pojawia się wcale, bo żaden jego wpis nie pasuje do warunku. Zrzut: kw3.jpg.
Typowe błędy
Bez GROUP BY zapytanie zwraca jeden wiersz z liczbą 4 (na MariaDB z jakąś jedną nazwą miesiąca) - klucz wymaga wyniku dla każdego miesiąca osobno.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT dataZadania, wpis FROM zadania WHERE miesiac = 'sierpien';-- Zapytanie 2SELECT miesiac, rok FROM zadania WHERE dataZadania = '2020-08-07';-- Zapytanie 3SELECT miesiac, COUNT(*) FROM zadania WHERE wpis LIKE 'Weterynarz%' GROUP BY miesiac;
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: nowy wpis na 9 sierpnia 2020
Kryteria:
R.1.6 Utworzono zapytanie 4 aktualizujące pole wpis dla zadania z datą 2020-08-09, nowy wpis to „Wycieczka: Zalew Mietkowski”. W pliku z kwerendami lub na zrzucie istnieje zapis np.: UPDATE zadania SET wpis='Wycieczka: Zalew Mietkowski' WHERE dataZadania="2020-08-09"; oraz wynik działania udokumentowano zrzutem, na którym widoczny jest komunikat o poprawnej aktualizacji lub tabela ze zaktualizowanym wpisem
ok. 2 min
Polecenie z arkusza
Zapytanie 4: aktualizujące pole wpis dla zadania z datą 9 sierpnia 2020, nowy wpis to „Wycieczka: Zalew Mietkowski”
UPDATE zadania - zmiana danych w istniejących wierszach,
SET wpis = 'Wycieczka: Zalew Mietkowski' - nowa wartość pola,
WHERE dataZadania = '2020-08-09' - tylko ten jeden dzień; bez warunku zmieniłyby się wszystkie 63 wpisy.
phpMyAdmin pokazuje komunikat o jednym zmodyfikowanym rekordzie; zrzut kw4.jpg ma ten komunikat i rekord po zmianie. To zapytanie wróci w skrypcie formularza - z tekstem z pola edycyjnego zamiast stałego wpisu.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT dataZadania, wpis FROM zadania WHERE miesiac = 'sierpien';-- Zapytanie 2SELECT miesiac, rok FROM zadania WHERE dataZadania = '2020-08-07';-- Zapytanie 3SELECT miesiac, COUNT(*) FROM zadania WHERE wpis LIKE 'Weterynarz%' GROUP BY miesiac;-- Zapytanie 4UPDATE zadania SET wpis = 'Wycieczka: Zalew Mietkowski' WHERE dataZadania = '2020-08-09';
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 8-21 · po tym etapie masz 17 z 34 kryteriów (pkt)
Krok 8: Logo 120 × 120 px
Kryteria:
R.2.1 Plik logo2.png przeskalowano do wymiarów 120 px na 120 px (± 2 px)
ok. 2 min
Polecenie z arkusza
Plik logo2.png, wypakowany z archiwum, należy przeskalować dokładnie do wymiarów 120 px na 120 px
W GIMP-ie: Obraz → Skaluj obraz, szerokość 120 px - przy zablokowanym łańcuchu proporcji wysokość sama zmieni się na 120, bo obraz jest kwadratem 300 × 300. Potem Plik → Nadpisz logo2.png (albo Wyeksportuj jakologo2.png); format PNG zachowuje przezroczyste tło wokół koła. logo1.png z archiwum nie jest w zadaniu używany.
Typowe błędy
Zmiana samego atrybutu width w HTML-u nie zmienia pliku - klucz sprawdza wymiary pliku logo2.png (120 × 120 px, ±2 px).
Podgląd strony po tym kroku
Krok 9: Plik organizer.php w HTML5
ok. 2 min
Polecenie z arkusza
Składa się ze strony o nazwie organizer.php
Deklaracja <!DOCTYPE html> i szkielet strony. Rozszerzenie .php, bo strona będzie miała skrypty; na egzaminie folder z numerem zdającego leży w htdocs XAMPP-a i strona otwiera się przez http://localhost/..., inaczej PHP się nie wykona.
R.2.2 Witrynę internetową zapisano w pliku organizer.php oraz zapisano jawnie standard kodowania polskich znaków i deklarację HTML5 <!DOCTYPE HTML> i zadeklarowano język witryny: polski np. <html lang="pl">
ok. 1 min
Polecenie z arkusza
Zadeklarowany język witryny: polski
Atrybut lang="pl" w znaczniku <html>. Razem z nazwą pliku, deklaracją HTML5 i kodowaniem to jedno kryterium klucza (R.2.2).
R.3.4 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl5.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 styl5.css prawidłowo połączony z kodem strony
Nazwa pliku: styl5.css - z cyfrą 5. Całe formatowanie ma pochodzić z tego pliku, bez atrybutów style.
Typowe błędy
Klucz odbiera R.3.4 także wtedy, gdy choć jeden selektor nie trafia w blok (np. kropka zamiast #).
Krok 14: Bloki: trzy bloki banera, blok główny i stopka
Kryteria:
R.2.4 Układ strony zdefiniowano dzieląc ją na: 3 bloki banera, blok główny i stopkę. Zastosowano znaczniki sekcji
ok. 2 min
Polecenie z arkusza
Podział strony na bloki: trzy bloki banera, poniżej blok główny, w którym znajdują się generowane skryptem bloki kalendarza, 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
Trzy bloki banera to trzy znaczniki <header> - wszystkie z klasą banner (wspólne kolory i wysokość) i każdy z własnym identyfikatorem (banner1 - banner3, różne szerokości). Blok główny to <main>, stopka - <footer>. Bloki kalendarza nie są pisane w HTML-u: wygeneruje je Skrypt 1 wewnątrz <main>.
Krok 16: Drugi blok banera: formularz POST do tej samej strony
Kryteria: ,
R.2.6 W drugim bloku banera umieszczono formularz, zastosowano znacznik <form>
R.3.3 Zdefiniowano dla formularza metodę POST
ok. 2 min
Polecenie z arkusza
Zawartość drugiego bloku banera: formularz wysyłający dane metodą bezpieczną do tej samej strony, zawierający pole edycyjne i przycisk
<form> z atrybutem action="organizer.php" - dane wracają do tej samej strony - i method="post". Dane idą w treści żądania, a nie w adresie strony, więc wpisanego tekstu nie widać na pasku adresu ani w historii.
⚠️ Rozbieżność arkusz-klucz: arkusz każe wysyłać dane „metodą bezpieczną”, a w specyfikacji HTTP (RFC 9110) metody bezpieczne (safe) to GET i HEAD - te, które nie zmieniają danych na serwerze. Klucz CKE (R.3.3) wymaga POST - na egzaminie punkt daje wersja z klucza.
Typowe błędy
Formularz bez method wysyła dane metodą GET (domyślną) - klucz nie uzna R.3.3, a skrypt czytający $_POST niczego nie dostanie.
<input type="text"> z podpisem w <label>. Atrybut name="event" to nazwa, pod którą tekst trafi do skryptu ($_POST["event"]), a for w etykiecie wskazuje id pola - kliknięcie podpisu ustawia kursor w polu.
Typowe błędy
Pole bez atrybutu name nie jest wysyłane wcale - skrypt formularza nie ma czego zapisać (R.5.6, R.5.7).
R.2.7 Na stronie umieszczono pole do wprowadzania danych oraz przycisk "OK"
R.3.2 Przycisk ma funkcję wysyłania danych (input lub button z typem submit lub button bez typu)
ok. 1 min
Polecenie z arkusza
Przycisk o treści „OK” wysyłający zawartość formularza
<button type="submit"> - przycisk wysyłający formularz (klucz uznaje też <input type="submit" value="OK"> albo <button> bez typu, bo w formularzu domyślnie wysyła).
R.2.5 W banerze pierwszym zapisano nagłówek h1: "Organizer: SIERPIEŃ" oraz w stopce zapisano paragraf
ok. 1 min
Polecenie z arkusza
Zawartość stopki: Paragraf (akapit) o treści: „Stronę wykonał: ”, dalej wstawiony numer zdającego
Akapit <p> w <footer>. Na egzaminie w miejscu imienia i nazwiska wpisuje się numer zdającego, czyli PESEL; w tym rozwiązaniu stoi tam „Bartosz Bryniarski”. Strona ma już nagłówek <h1> w pierwszym bloku banera i akapit w stopce (R.2.5).
Kroki 22-30 · po tym etapie masz 27 z 34 kryteriów (pkt)
Krok 22: Krój czcionki dla wszystkich elementów
Kryteria:
R.4.1 Ustawiono domyślne formatowanie wszystkich selektorów (*): krój czcionki Tahoma
ok. 1 min
Polecenie z arkusza
Ustawione domyślne wartości dla wszystkich selektorów stylu CSS: krój czcionki Tahoma
Selektor uniwersalny * - krój dostają wszystkie elementy, także pole formularza i przycisk.
styl5.cssCSSnowy plik
* {font-family: Tahoma;}
Podgląd strony po tym kroku (organizer.php)
Krok 23: Wszystkie bloki banera
Kryteria:
R.4.5 Ustawiono wysokość 120px dla trzech bloków banera
ok. 1 min
Polecenie z arkusza
Dla wszystkich bloków banera: kolor tła #7DA453, biały kolor czcionki, wysokość 120 px
Jedna reguła dla klasy .banner - trzy bloki mają ją w HTML-u, więc wspólne właściwości nie są powtarzane trzy razy. Wysokość 120 px to tyle, ile ma logo.
R.4.4 Ustawiono szerokość bloków banera: 40% pierwszy i drugi oraz 20% trzeci (width lub grid- template-columns lub flex) poprawne również rozwiązanie bez szerokości dla trzeciego bloku jeśli bloki wstawiono w kontener nadrzędny
ok. 1 min
Polecenie z arkusza
Dodatkowo pierwszy i drugi blok banera ma szerokość 40%, trzeci 20%
Szerokości są różne, więc idą do reguł z identyfikatorami. 40% + 40% + 20% = 100% - trzy bloki zajmą razem całą szerokość strony.
R.4.8 Ustawiono dla bloku kalendarza: kolor tła #AED581, szerokość 200px, wysokość 100px, marginesy zewnętrzne (margin) 7px, obramowanie 1px solid #7DA453 (np. za pomocą klasy. Użycie id jest błędem)
ok. 2 min
Polecenie z arkusza
Dla bloku kalendarza: kolor tła #AED581, szerokość 200 px, wysokość 100 px, marginesy zewnętrzne 7 px, obramowanie o szerokości 1 px, linią ciągłą o kolorze #7DA453
Bloków kalendarza będzie 31, więc formatuje je klasa .day - skrypt nada ją każdemu blokowi. Klucz przy R.4.8 pisze wprost, że użycie identyfikatora jest błędem: id ma być na stronie jeden, a bloków jest wiele. margin: 7px to odstęp z każdej strony bloku, border: 1px solid #7DA453 - obramowanie w kolorze banera.
R.4.7 Ustawiono wyrównanie tekstu do środka dla selektora h5
ok. 1 min
Polecenie z arkusza
Dla selektora nagłówka piątego stopnia: wyrównanie tekstu do środka
Selektor znacznika h5 - w nagłówkach piątego stopnia skrypt wypisze daty. Uwaga pod listą stylów każe tu użyć selektora znacznika, a nie klasy, i klucz (R.4.7) uznaje tylko taki zapis.
R.4.6 Ustawiono marginesy wewnętrzne (padding) 5px dla stopki oraz wewnętrzny górny (padding-top) 50px dla selektora form
ok. 1 min
Polecenie z arkusza
Dla selektora formularza: margines wewnętrzny górny: 50 px
Selektor znacznika form, właściwość padding-top - formularz zsuwa się mniej więcej na środek wysokości banera, jak na obrazie 2. Margines wewnętrzny stopki jest już ustawiony (R.4.6).
Typowe błędy
margin-top zamiast padding-top albo reguła dla klasy formularza zamiast znacznika form - klucz (R.4.6) uznaje tylko margines wewnętrzny dla selektora form.
R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z obrazem 2 w arkuszu (Uwaga! Blok główny nie musi zawierać bloków kalendarza; 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ł strony na bloki: trzy bloki banera, poniżej blok główny, w którym znajdują się generowane skryptem bloki kalendarza, 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
float: left dostają bloki banera (stają obok siebie: 40% + 40% + 20%) i bloki kalendarza (układają się w rzędy po tyle, ile zmieści szerokość okna - blok z marginesami zajmuje 216 px, więc sześć w rzędzie, jak na obrazie 2, mieści się od szerokości strony około 1310 px (6 × 216 px plus marginesy body; sprawdzone w Chrome), a w węższym oknie jest ich pięć). Banery wypełniają cały rząd, więc pierwszy blok kalendarza zaczyna się pod nimi. Stopka z clear: both staje pod wszystkimi pływającymi blokami. Klucz przy R.3.1 zaznacza, że blok główny nie musi mieć bloków kalendarza - ocenia się układ.
Kroki 31-36 · po tym etapie masz 34 z 34 kryteriów (pkt)
Krok 31: Połączenie z bazą i zamknięcie połączenia
Kryteria: ,
R.5.1 Skrypt zawiera działające połączenie z serwerem bazy danych i wybór bazy kalendarz
R.5.2 Ostatnią operacją na bazie jest jej zamknięcie (zgodne ze składnią)
ok. 2 min
Polecenie z arkusza
Skrypt łączy się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie kalendarz
Na stronie są dwa bloki PHP: skrypt obsługujący formularz w drugim bloku banera, zaraz pod formularzem, i Skrypt 1 w bloku głównym. Kolejność ma znaczenie: skrypt formularza wykonuje się pierwszy, więc zapisuje nowy wpis do bazy, zanim Skrypt 1 odczyta kalendarz - zmiana jest widoczna od razu po wysłaniu, jak na obrazie 2. Dlatego to on otwiera połączenie (mysqli_connect z czterema argumentami: serwer, użytkownik, puste hasło, baza; uchwyt w zmiennej $connection), a Skrypt 1 zamyka je na końcu - kolejne instrukcje będą dopisywane nad mysqli_close, więc zamknięcie zostanie ostatnią operacją na bazie (R.5.2). Od tego kroku podgląd to wynik prawdziwego uruchomienia strony.
R.5.6 W skrypcie obsługującym formularz zastosowano tablicę $_POST, zapis jest poprawny składniowo i logicznie
ok. 2 min
Polecenie z arkusza
Skrypt pobiera dane z pola edycyjnego
Tekst z pola jest w tablicy $_POST pod nazwą z atrybutu name, czyli $_POST["event"]. Przy pierwszym otwarciu strony formularz nie był jeszcze wysłany i tego elementu tablicy nie ma - dlatego odczyt stoi w warunku isset. Bez niego PHP 8 wypisałby ostrzeżenie „Undefined array key”, a zapytanie z kolejnego kroku wykonywałoby się przy każdym wejściu na stronę.
R.5.7 Skrypt obsługujący formularz uaktualnia dane w bazie danych. Dane pobrane z formularza są wpisane do rekordu o dacie 2020-08-09. Należy sprawdzić w phpMyAdmin czy po wciśnięciu przycisku baza została uaktualniona, nie jest wymagane uaktualnienie na stronie
ok. 3 min
Polecenie z arkusza
Następnie za pomocą zmodyfikowanego zapytania 4 uaktualnia dane w bazie danych tak, że dane w polu wpis zostały pobrane z formularza. Aby uprościć zadanie skrypt wprowadza wpis zawsze do rekordu o dacie 2020-08-09.
Zapytanie 4 z jedną zmianą: zamiast stałego tekstu „Wycieczka: Zalew Mietkowski” jest zmienna $event - PHP wstawia jej wartość do napisu w cudzysłowach, a apostrofy wokół niej są apostrofami SQL-a. Warunek zostaje ten sam: zawsze dzień 2020-08-09. mysqli_query wysyła zapytanie; UPDATE nie zwraca wierszy, więc wynik nie jest potrzebny. Sprawdzone na bazie: po wysłaniu formularza z tekstem „zakupy” rekord z 9 sierpnia ma wpis zakupy - to sprawdza egzaminator w phpMyAdmin (R.5.7).
R.5.3 Skrypt 1 wysyła do bazy danych zapytanie 1 lub skrypt obsługujący formularz wysyła zmodyfikowane zapytanie 4
ok. 1 min
Polecenie z arkusza
Wysyła do bazy danych zapytanie 1
Zapytanie 1 bez zmian, w zmiennej $query. Nazwy $query i $result powtarzają się po skrypcie formularza - tamto zapytanie zostało już wykonane, więc można ich użyć ponownie. mysqli_query wysyła zapytanie, a w $result zostaje 31 wierszy do odczytania.
Krok 35: Skrypt 1: blok kalendarza z datą dla każdego wiersza
Kryteria:
R.5.4 Skrypt 1 wyświetla w bloku głównym bloki zdefiniowane za pomocą znaczników sekcji. Liczba wygenerowanych bloków odpowiada liczbie wierszy zwróconych zapytaniem
ok. 3 min
Polecenie z arkusza
Za pomocą znacznika sekcji definiuje blok, a w nim wyświetla dane przesłane skryptem dotyczące jednego wiersza. Blok jest zgodny z Obrazem 3 oraz jest w nim wyświetlone: data zadania w nagłówku piątego stopnia
Pętla while z mysqli_fetch_row przechodzi po wierszach wyniku; $row[0] to dataZadania, pierwsze pole zapytania. Dla każdego wiersza skrypt otwiera znacznik <section class="day"> (klasa z reguły stylu bloku kalendarza; cudzysłowy atrybutu wewnątrz napisu PHP poprzedza ukośnik \"), wypisuje datę w <h5> i zamyka blok. Podgląd: 31 zielonych bloków z datami - tyle, ile wierszy zwraca zapytanie (R.5.4).
R.5.5 Skrypt 1 wyświetla datę zadania w nagłówku h5 oraz pole wpis w paragrafie
ok. 2 min
Polecenie z arkusza
Pole wpis w paragrafie (akapicie)
Drugie pole zapytania, $row[1] (wpis), w akapicie <p> pod datą - blok wygląda jak na obrazie 3. Dni bez zadań mają w bazie pusty tekst, więc ich akapit jest pusty. Podgląd to strona po wysłaniu formularza z wpisem „zakupy”: skrypt formularza zapisał go do 9 sierpnia, zanim Skrypt 1 odczytał bazę, więc blok 2020-08-09 pokazuje „zakupy” zamiast „Wycieczka: Zalew Mietkowski” z zapytania 4 - jak na obrazie 2.
Kroki 37-39 · po tym etapie masz 34 z 34 kryteriów (pkt)
Krok 37: Formularz: apostrof i puste pole
ok. 4 min
Polecenie z arkusza
Następnie za pomocą zmodyfikowanego zapytania 4 uaktualnia dane w bazie danych tak, że dane w polu wpis zostały pobrane z formularza. Aby uprościć zadanie skrypt wprowadza wpis zawsze do rekordu o dacie 2020-08-09.
Wersja egzaminacyjna sprawdzona dwoma wpisami, które zdarzają się naprawdę:
Urodziny Ani's - apostrof z tekstu zamyka napis w zapytaniu SQL; MariaDB zgłasza błąd składni, a PHP 8 zamienia go w wyjątek mysqli_sql_exception i strona urywa się w połowie banera (sprawdzone - kalendarza nie ma wcale). Ten sam mechanizm pozwala wpisać w pole fragment SQL i zmienić zapytanie,
puste pole - kliknięcie OK bez tekstu kasuje wpis z 9 sierpnia (sprawdzone).
Poprawka: zapytanie przygotowane (mysqli_prepare ze znakiem ? w miejscu wartości, mysqli_stmt_bind_param z typem "s" - tekst, mysqli_stmt_execute) - wartość idzie do bazy osobno i żaden znak jej nie rozbije, oraz warunek z trim: same spacje też nie zmieniają wpisu. Podgląd: kalendarz po wysłaniu wpisu z apostrofem. Stare linie zostały w komentarzu. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
Wpis pochodzi od użytkownika, a Skrypt 1 wkleja go do strony bez zmian. Test na wersji egzaminacyjnej: wpis <b>zakupy</b> pokazuje się pogrubiony - przeglądarka wykonała znaczniki z formularza, a tak samo wykonałaby <script>. htmlspecialchars zamienia < i > na encje, więc wpis pokazuje się dosłownie, razem ze znakami. Przy okazji mysqli_fetch_assoc zamiast numerów kolumn - $day["dataZadania"] czyta się łatwiej niż $row[0] - a ?? "" zastępuje wartość NULL pustym tekstem, bo od PHP 8.1 htmlspecialchars(null) daje ostrzeżenie o przestarzałym wywołaniu. Podgląd: wpis ze znacznikami po poprawce. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
Następnie za pomocą zmodyfikowanego zapytania 4 uaktualnia dane w bazie danych tak, że dane w polu wpis zostały pobrane z formularza. Aby uprościć zadanie skrypt wprowadza wpis zawsze do rekordu o dacie 2020-08-09.
Wpis „Śniadanie u babci w Łodzi” zapisuje się w bazie jako „?niadanie u babci w ?odzi” - sprawdzone na MariaDB z XAMPP-a. Przyczyna nie leży w PHP: tabela zadania z pliku baza5.sql jest utworzona z kodowaniem latin1 (DEFAULT CHARSET=latin1), a w nim nie ma liter „ś”, „ł”, „ą” - baza zastępuje je znakiem zapytania bez żadnego komunikatu („ó” akurat jest w latin1, więc przechodzi). Dane z arkusza nie mają polskich liter (stąd sierpien), dlatego zadanie tego nie pokazuje.
Poprawka to jedno zapytanie na strukturze tabeli, w pliku kodowanie.sql: ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 zmienia kodowanie tabeli i przepisuje istniejące dane (wpisy z arkusza zostają bez zmian - sprawdzone). Po nim ten sam wpis zapisuje się poprawnie. Na egzaminie tego nie rób - zrzuty i zapytania mają dotyczyć tabeli z importu, a klucz tego nie sprawdza.
kodowanie.sqlSQLnowy plik
-- Zmiana kodowania tabeli zadania (poza zadaniem egzaminacyjnym)ALTERTABLE zadania CONVERTTOCHARACTERSET utf8mb4 COLLATE utf8mb4_polish_ci;
Podgląd strony po tym kroku (organizer.php)
Etap 6: Oddanie pracy
Krok 40 · po tym etapie masz 34 z 34 kryteriów (pkt)
Krok 40: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
Po zakończeniu pracy utwórz plik tekstowy. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowana była poprawność działania witryny. Nazwij plik przeglądarka.txt i zapisz go w folderze z numerem zdającego. Nagraj płytę z rezultatami pracy.
W przeglądarka.txt wystarczy nazwa przeglądarki, w której była sprawdzana strona.
W folderze z numerem zdającego: import.png, kw1.jpg - kw4.jpg, kwerendy.txt, logo2.png (już 120 × 120 px), organizer.php, przeglądarka.txt i styl5.css. Po nagraniu płyty trzeba sprawdzić jej odczyt i opisać ją numerem zdającego.
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
To jedno z możliwych rozwiązań. Egzaminator ocenia spełnienie kryteriów z klucza odpowiedzi, a nie zgodność z tym kodem - inna, poprawna droga też daje punkty.
Autor rozwiązania: Bartosz Bryniarski. Licencja CC BY-NC 4.0 - kopiowanie i przeróbki do celów niekomercyjnych, z podaniem autora i źródła (link do tej strony) (zasady wykorzystania). Treść arkusza i klucza oceniania pochodzi z CKE.