INF.03-03-25.01-SGStyczeń 2025 · 49 kroków · ok. 102 min · 43 kryteria z klucza
Rozwiązanie krok po kroku: Kalendarz imienin w PHP (Nowoczesny kod (grid, PDO))
To drugi sposób rozwiązania tego samego arkusza: baza kalendarz z czterema zapytaniami i eksportem CSV, animacja GIF z dwunastu klatek oraz strona kalendarz.php z tabelą, formularzem daty, listą i dwoma skryptami PHP - dzisiejsze imieniny i imieniny w dniu wybranym w formularzu. Obie wersje spełniają wszystkie 43 kryteria klucza - różni je sposób pisania kodu, nie wynik.
Czym ta wersja różni się od podstawowej:
siatka CSS z nazwanymi obszarami (grid-template-areas) zamiast float i clear - cały układ z ilustracji 2 w jednej regule, kolory w zmiennych CSS,
PHP na PDO z wyjątkami: cała praca z bazą na górze pliku, połączenie zamknięte, zanim zacznie się HTML, a w HTML tylko wypisywanie gotowych zmiennych,
jedna funkcja namesForDay() z zapytaniem przygotowanym obsługuje oba skrypty - data idzie do bazy jako parametr, a nie wklejona w treść zapytania,
sprawdzenie daty z formularza: format, istnienie dnia (31 lutego odpada) i rok 2024 - po stronie serwera, bo min, max i required działają tylko w przeglądarce,
htmlspecialchars przy każdym wypisaniu (krótka funkcja e()), formularz pamięta wybraną datę.
Kroki nadal idą zdanie po zdaniu za treścią arkusza. Podgląd w każdym kroku z PHP to wynik prawdziwego uruchomienia kodu z tego kroku w PHP 8.2 na bazie z arkusza; data „dzisiejsza” jest ustawiona na dzień z ilustracji 2 (czwartek 25 maja 2023), a od Skryptu 2 formularz wysyła 24 stycznia 2024. Baza i klatki animacji pochodzą z prawdziwego archiwum pliki13.
Jak liczą się punkty. Klucz ma 43 kryteria (R.1.1 - R.5.10), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 33 punkty. 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-8 · po tym etapie masz 7 z 43 kryteriów (pkt)
Krok 1: Baza danych kalendarz
ok. 2 min
Polecenie z arkusza
Utwórz bazę danych o nazwie kalendarz, z zestawem polskich znaków (np. utf8_unicode_ci).
Archiwum pliki13.7z ma hasło k@L3ndarz; zawiera baza.sql i dwanaście klatek kalendarz01.png - kalendarz12.png. W phpMyAdmin: Nowa, nazwa kalendarz, porównywanie z polskimi znakami, np. utf8mb4_polish_ci albo utf8_unicode_ci z przykładu w arkuszu.
Tabela z baza.sql ma zestaw znaków zapisany we własnej definicji (DEFAULT CHARSET=utf8), więc dostaje domyślne porównywanie tego zestawu - utf8_general_ci - niezależnie od wyboru dla bazy.
Krok 2: Import tabeli z pliku baza.sql
ok. 2 min
Polecenie z arkusza
Do utworzonej bazy zaimportuj tabele z pliku baza.sql z rozpakowanego archiwum.
Zaznaczona baza kalendarz, Import → baza.sql → Wykonaj. Jedna tabela imieniny: 366 wierszy, data tekstem w formacie mm-dd (7 listopada to 11-07), imiona w dopełniaczu, po kilka w polu.
Krok 3: Zrzut ekranu import.png
Kryteria:
R.1.1 Wykonany import tabeli do bazy danych kalendarz, co jest udokumentowane w pliku import.png
ok. 2 min
Polecenie z arkusza
Wykonaj zrzut ekranu po imporcie. Zapisz zrzut w formacie PNG pod nazwą import. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel.
Print Screen i zapis jako import.png - komunikat o udanym imporcie i tabela imieniny w drzewie bazy.
Typowe błędy
Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).
Krok 4: Zapytanie 1: kiedy imieniny Karola
Kryteria: ,
R.1.2 Zapisany plik kwerendy.txt zawierający co najmniej jedno zapytanie SQL, wynikające z treści zadania
R.1.3 Wykonane zapytanie 1 wybierające z tabeli imieniny jedynie daty, w których są imieniny Karola. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT data FROM imieniny WHERE imiona LIKE "%Karola%"; ("%Karol%" jest błędem ) oraz wynik działania udokumentowany zrzutem, na którym widoczne są jedynie trzy rekordy z wartościami: 05-30, 06-03, 11-04
ok. 3 min
Polecenie z arkusza
Zapytanie 1: wybierające z tabeli imieniny jedynie daty, w których są imieniny Karola.
Każda klauzula w osobnej linii, napis we wzorcu w apostrofach (standard SQL):
SELECT data FROM imieniny - „jedynie daty”,
WHERE imiona LIKE '%Karola%' - imię w dowolnym miejscu pola.
Pułapka: imiona są w dopełniaczu, a w bazie są też Karoliny. Wzorzec %Karol% złapałby i je - dlatego forma „Karola”. Wynik: 05-30, 06-03 i 11-04. Zapytanie trafia do kwerendy.txt, zrzut do kw1.png.
Typowe błędy
LIKE '%Karol%' klucz wprost nazywa błędem - wynik obejmuje imieniny Karoliny.
kwerendy.txtTekstnowy plik
-- Zapytanie 1SELECT dataFROM imieninyWHERE imiona LIKE '%Karola%';
Podgląd strony po tym kroku
Krok 5: Zapytanie 2: imieniny 4 maja
Kryteria:
R.1.4 Wykonane zapytanie 2 wybierające jedynie imiona osób, które obchodzą imieniny 4 maja. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imiona FROM imieniny WHERE data = "05-04"; oraz wynik działania udokumentowany zrzutem, na którym widoczny jest dokładnie 1 rekord z danymi: Moniki, Floriana, Władysława
ok. 1 min
Polecenie z arkusza
Zapytanie 2: wybierające jedynie imiona osób, które obchodzą imieniny 4 maja.
4 maja w formacie bazy to '05-04' - miesiąc, potem dzień. Wynik: „Moniki, Floriana, Władysława”. Zrzut: kw2.png. Oba skrypty PHP wykonają to samo zapytanie, tylko z inną datą - w tej wersji jako parametr zapytania przygotowanego.
Typowe błędy
data = '04-05' (dzień-miesiąc) szuka 5 kwietnia.
kwerendy.txtTekstzmienione: 5 linii
-- Zapytanie 1SELECT dataFROM imieninyWHERE imiona LIKE '%Karola%';-- Zapytanie 2SELECT imionaFROM imieninyWHERE data = '05-04';
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: ile dat z imieniem z cząstką „mir”
Kryteria:
R.1.5 Wykonane zapytanie 3 zliczające daty, w których imieniny obchodzi osoba, której imię zawiera cząstkę "mir". W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT COUNT(data) FROM imieniny WHERE imiona LIKE "%mir%"; (COUNT możliwe również z * lub innym polem) oraz wynik działania udokumentowany zrzutem, na którym widoczna jest jedynie wartość 23
ok. 2 min
Polecenie z arkusza
Zapytanie 3: obliczające, ile jest dat, w których imieniny obchodzi osoba, której imię zawiera cząstkę mir (np. Miron, Dobromir, Sędzimira).
COUNT(*) liczy wiersze spełniające warunek, a alias AS liczba_dat daje kolumnie czytelny nagłówek zamiast „COUNT(*)”. Porównywanie kolumny (utf8_general_ci) nie rozróżnia wielkości liter, więc %mir% łapie też „Mirosława”. Wynik: 23. Zrzut: kw3.png.
kwerendy.txtTekstzmienione: 5 linii
-- Zapytanie 1SELECT dataFROM imieninyWHERE imiona LIKE '%Karola%';-- Zapytanie 2SELECT imionaFROM imieninyWHERE data = '05-04';-- Zapytanie 3SELECT COUNT(*) AS liczba_datFROM imieninyWHERE imiona LIKE '%mir%';
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: nowe pole zyczenia
Kryteria:
R.1.6 Wykonane zapytanie 4 dodające do tabeli imieniny pole zyczenia typu napisowego, które pomieści 500 znaków. W pliku z kwerendami lub na zrzucie istnieje zapis np.: ALTER TABLE imieniny ADD COLUMN zyczenia VARCHAR(500); (COLUMN opcjonalne, dowolny typ tekstowy o długości min. 500 ) oraz wynik działania udokumentowany zrzutem, na którym widoczna jest informacja o poprawnym wykonaniu zapytania lub tabela z dodaną kolumną
ok. 2 min
Polecenie z arkusza
Zapytanie 4: dodające do tabeli imieniny pole zyczenia typu napisowego, które pomieści 500 znaków.
ALTER TABLE ... ADD COLUMN zyczenia VARCHAR(500) - tekst do 500 znaków (pasuje też TEXT). Istniejące wiersze dostają w nowej kolumnie NULL. Zrzut kw4.png: komunikat albo struktura tabeli z nową kolumną.
kwerendy.txtTekstzmienione: 4 linie
-- Zapytanie 1SELECT dataFROM imieninyWHERE imiona LIKE '%Karola%';-- Zapytanie 2SELECT imionaFROM imieninyWHERE data = '05-04';-- Zapytanie 3SELECT COUNT(*) AS liczba_datFROM imieninyWHERE imiona LIKE '%mir%';-- Zapytanie 4ALTER TABLE imieninyADD COLUMN zyczenia VARCHAR(500);
Podgląd strony po tym kroku
Krok 8: Eksport tabeli do imieniny.csv
Kryteria:
R.1.7 Zapisany plik imieniny w formacie CSV, zawierający wyeksportowane rekordy z tabeli imieniny
ok. 2 min
Polecenie z arkusza
Wyeksportuj dane z tabeli imieniny do pliku w formacie CSV i nadaj mu nazwę imieniny.
Tabela imieniny → Eksport → format CSV → Eksportuj. Plik imieniny.csv trafia do folderu z numerem zdającego: 366 wierszy, wartości w cudzysłowach oddzielone przecinkami, pusta kolumna zyczenia jako NULL (R.1.7).
Typowe błędy
Eksport całej bazy w formacie SQL to inny plik niż wymagany CSV z tabeli imieniny.
Kroki 9-29 · po tym etapie masz 22 z 43 kryteriów (pkt)
Krok 9: Warstwy animacji: dwanaście klatek
Kryteria:
R.2.1 Utworzony plik kalendarz.gif o rozmiarze 500 x 500 px, z przezroczystością, zawierający animację złożoną z plików, kolejno od kalendarz01.png do kalendarz12.png (widać kolejne ruchy strzałki-słońca ), jeden obraz na klatkę
ok. 4 min
Polecenie z arkusza
Na animację składają się pliki, kolejno: kalendarz01.png, kalendarz02.png, kalendarz03.png, kalendarz04.png, kalendarz05.png, kalendarz06.png, kalendarz07.png, kalendarz08.png, kalendarz09.png, kalendarz10.png, kalendarz11.png i kalendarz12.png. Nie należy zmieniać właściwości grafik: przezroczystości i wymiarów 500 x 500 px.
GIMP: Plik → Otwórz jako warstwy, wszystkie dwanaście plików naraz. Warstwa to klatka, a najniższa warstwa jest pierwszą klatką - kalendarz01 na dole listy, kalendarz12 na górze (w razie potrzeby Warstwa → Stos → Odwróć kolejność warstw). Bez skalowania i spłaszczania - 500 × 500 z przezroczystym tłem (R.2.1).
Krok 10: Eksport kalendarz.gif: 350 ms na klatkę
Kryteria: ,
R.2.1 Utworzony plik kalendarz.gif o rozmiarze 500 x 500 px, z przezroczystością, zawierający animację złożoną z plików, kolejno od kalendarz01.png do kalendarz12.png (widać kolejne ruchy strzałki-słońca ), jeden obraz na klatkę
R.2.2 Ustawiony czas wyświetlenia obrazów animacji na 350 ms, co jest udokumentowane zrzutem parametry_animacji.png
ok. 4 min
Polecenie z arkusza
Każdy obraz jest pokazywany w animacji przez 350 ms, jedna klatka na warstwę. Udokumentuj ustawienie parametru za pomocą zrzutu ekranu o nazwie parametry_animacji.png. Zrzut musi obejmować cały obszar ekranu z widocznym paskiem zadań.
Plik → Eksportuj jakokalendarz.gif: Jako animację, opóźnienie 350 ms, Jedna klatka na warstwę (zastąp) i Użyj opóźnienia wprowadzonego powyżej dla wszystkich klatek - GIMP czyta też opóźnienia z nazw warstw, a to pole każe je zignorować. Przed kliknięciem Eksportuj zrzut całego ekranu z tym oknem: parametry_animacji.png (R.2.2).
Typowe błędy
Eksport bez „Jako animację” zapisuje jedną spłaszczoną klatkę.
Podgląd strony po tym kroku
Krok 11: Plik kalendarz.php w HTML5
Kryteria:
R.2.3 Witryna internetowa zapisana w pliku kalendarz.php oraz zapisany jawnie standard kodowania polskich znaków, deklaracja HTML5 <!DOCTYPE HTML>, zadeklarowany język witryny: polski np. <html lang="pl"> oraz nadany tytuł strony "Kalendarz”, Strona zawiera sekcje head i body
ok. 2 min
Polecenie z arkusza
Cechy witryny: Składa się ze strony o nazwie kalendarz.php. Zapisana w języku HTML5.
Rozszerzenie .php, bo dojdą skrypty - na razie to zwykły HTML5. Na egzaminie plik leży w htdocs XAMPP-a i otwiera się go przez http://localhost/....
R.2.3 Witryna internetowa zapisana w pliku kalendarz.php oraz zapisany jawnie standard kodowania polskich znaków, deklaracja HTML5 <!DOCTYPE HTML>, zadeklarowany język witryny: polski np. <html lang="pl"> oraz nadany tytuł strony "Kalendarz”, Strona zawiera sekcje head i body
R.2.3 Witryna internetowa zapisana w pliku kalendarz.php oraz zapisany jawnie standard kodowania polskich znaków, deklaracja HTML5 <!DOCTYPE HTML>, zadeklarowany język witryny: polski np. <html lang="pl"> oraz nadany tytuł strony "Kalendarz”, Strona zawiera sekcje head i body
ok. 1 min
Polecenie z arkusza
Jawnie zastosowany właściwy standard kodowania polskich znaków.
<meta charset="UTF-8"> jako pierwszy element <head>.
R.2.3 Witryna internetowa zapisana w pliku kalendarz.php oraz zapisany jawnie standard kodowania polskich znaków, deklaracja HTML5 <!DOCTYPE HTML>, zadeklarowany język witryny: polski np. <html lang="pl"> oraz nadany tytuł strony "Kalendarz”, Strona zawiera sekcje head i body
ok. 1 min
Polecenie z arkusza
Tytuł strony widoczny na karcie przeglądarki: „Kalendarz”.
<title> - napis na karcie. <meta name="viewport"> każe telefonowi pokazać stronę w jego szerokości - arkusz tego nie wymaga.
R.3.2 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl.css, formatowanie CSS 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 styl.css prawidłowo połączony z kodem strony.
W tym arkuszu styl.css, bez „e”. <link> bez ukośnika /> (HTML5).
Krok 16: Bloki: nagłówek, napis, trzy bloki, stopka
Kryteria:
R.2.4 Zdefiniowany układ strony dzielący ją na bloki: nagłówkowy, napisu, lewy, środkowy, prawy, stopki przy pomocy semantycznych znaczników sekcji języka HTML5 zgodnie z ich znaczeniem, w tym do części nagłówkowej - header, do stopki - footer. Dopuszcza się dodatkowe użycie bloków div lub section
ok. 2 min
Polecenie z arkusza
Podział strony na bloki: nagłówkowy, napisu, poniżej trzy bloki umieszczone obok siebie, na dole stopka. Podział zrealizowany za pomocą semantycznych znaczników sekcji języka HTML5 tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z ilustracją 2.
<header> i <footer> - jak wymaga klucz, blok napisu i trzy bloki treści jako <section> z identyfikatorami caption, left, middle, right (R.2.4). Kolejność w kodzie to kolejność czytania; gdzie bloki staną na ekranie, rozstrzygnie siatka CSS.
R.2.5 Umieszczone w bloku nagłówkowym <h1>: "Dni, miesiące, lata…", w bloku środkowym <h2>: "Sprawdź kto ma urodziny", w bloku prawym <h2> "Rodzaje kalendarzy" oraz przynajmniej jeden paragraf
ok. 1 min
Polecenie z arkusza
Zawartość bloku nagłówkowego: Nagłówek pierwszego stopnia o treści „Dni, miesiące, lata...”.
R.2.5 Umieszczone w bloku nagłówkowym <h1>: "Dni, miesiące, lata…", w bloku środkowym <h2>: "Sprawdź kto ma urodziny", w bloku prawym <h2> "Rodzaje kalendarzy" oraz przynajmniej jeden paragraf
ok. 1 min
Polecenie z arkusza
Zawartość bloku napisu: Paragraf z efektem działania Skryptu 1.
R.2.7 Pierwszy wiersz tabeli zawiera komórki nagłówkowe, zastosowany znacznik <th>
ok. 1 min
Polecenie z arkusza
Zawartość bloku lewego: Tabela o 2 kolumnach i 13 wierszach, z czego niektóre wiersze są scalone. Pierwszy wiersz zawiera komórki nagłówkowe. Treść i wygląd tabeli przedstawiony jest na ilustracji 3.
Pierwszy wiersz w <thead>, z komórkami nagłówkowymi <th> „liczba dni” i „miesiąc” (R.2.7). scope="col" mówi czytnikowi ekranu, że opisują kolumny.
Krok 20: Tabela: miesiące po 31 dni - komórka scalona
Kryteria:
R.2.6 W bloku lewym utworzona tabela o 2 kolumnach i 13 wierszach, z czego wiersze w pierwszej kolumnie są scalone zgodnie z ilustracją 3 arkusza egzaminacyjnego. Zastosowane znaczniki <table>, <tr>, <td> oraz atrybut rowspan
ok. 3 min
Polecenie z arkusza
Tabela o 2 kolumnach i 13 wierszach, z czego niektóre wiersze są scalone.
Wiersze z danymi w <tbody>. Liczba 31 stoi raz, w komórce z rowspan="7", która sięga przez siedem wierszy - w kolejnych sześciu jest już tylko nazwa miesiąca (R.2.6).
Semantycznie „31” opisuje całą grupę miesięcy, więc pasowałaby tu komórka nagłówkowa wiersza (<th scope="rowgroup">). Klucz R.2.6 wymienia jednak znaczniki <td> i atrybut rowspan dla scalonych wierszy, a ilustracja 3 pokazuje tę liczbę zwykłym krojem - dlatego zostaje <td rowspan>.
Typowe błędy
Liczba dni w każdym wierszu mimo rowspan przesuwa nazwy miesięcy do trzeciej, nieistniejącej kolumny.
R.2.6 W bloku lewym utworzona tabela o 2 kolumnach i 13 wierszach, z czego wiersze w pierwszej kolumnie są scalone zgodnie z ilustracją 3 arkusza egzaminacyjnego. Zastosowane znaczniki <table>, <tr>, <td> oraz atrybut rowspan
ok. 2 min
Polecenie z arkusza
Treść i wygląd tabeli przedstawiony jest na ilustracji 3.
To samo dla czterech miesięcy po 30 dni (rowspan="4") i ostatni wiersz bez scalania - „28 lub 29” i luty. Razem 13 wierszy (R.2.6).
R.2.5 Umieszczone w bloku nagłówkowym <h1>: "Dni, miesiące, lata…", w bloku środkowym <h2>: "Sprawdź kto ma urodziny", w bloku prawym <h2> "Rodzaje kalendarzy" oraz przynajmniej jeden paragraf
ok. 1 min
Polecenie z arkusza
Zawartość bloku środkowego: Nagłówek drugiego stopnia o treści: „Sprawdź kto ma urodziny”.
<h2> - treść z arkusza, choć strona pokazuje imieniny.
Krok 23: Formularz wysyłany metodą POST do tej samej strony
Kryteria: ,
R.2.8 W bloku środkowym umieszczony formularz z polem edycyjnym i przyciskiem "wyślij", zastosowany znacznik <form>
R.3.5 Formularz wysyła dane metodą POST do tego samego pliku (poprawne również bez atrybutu action )
ok. 2 min
Polecenie z arkusza
Formularz przesyłający dane metodą bezpieczną, do tego samego pliku.
„Metoda bezpieczna” w rozumieniu arkusza to method="post": data jedzie w treści żądania, a nie w adresie strony. W specyfikacji HTTP słowo „bezpieczna” znaczy co innego - metodę, która niczego nie zmienia na serwerze, czyli GET - ale klucz wymaga POST. Przy formularzu, który tylko odczytuje dane, w prawdziwym serwisie lepszy byłby GET: wynik dałoby się zapisać w zakładkach. Bez atrybutu action formularz wysyła dane do tego samego pliku (R.2.8, R.3.5).
R.3.4 Pole edycyjne jest typu date , minimalna wartość 2024-01-01, maksymalna 2024-12-31 oraz zawiera atrybut required
ok. 3 min
Polecenie z arkusza
Pole edycyjne o typie przeznaczonym do wprowadzania daty. Kalendarz wyświetla tylko daty z 2024 roku (od 1 stycznia 2024 do 31 grudnia 2024). Pole edycyjne jest wymagane. Pole edycyjne w stanie początkowym po naciśnięciu przycisku kalendarza zostało przedstawione na ilustracji 4.
type="date" z przyciskiem kalendarza, min i max w formacie rrrr-mm-dd, required (R.3.4),
name="date" - pod tą nazwą data trafi do $_POST,
arkusz nie przewiduje etykiety, więc opis dla czytnika ekranu niesie aria-label.
min, max i required sprawdza przeglądarka - żądanie da się jednak wysłać z pominięciem formularza, z dowolnym tekstem. Dlatego Skrypt 2 sprawdzi datę jeszcze raz.
Typowe błędy
Bez atrybutu name przeglądarka nie wysyła wartości pola - Skrypt 2 nic nie dostanie.
R.2.10 W bloku prawym umieszczony obraz z animacją z tekstem alternatywnym "Kalendarz Majów"
R.3.3 Kliknięcie animacji inicjuje otwarcie strony https://pl.wikipedia.org/wiki/Kalendarz_Majów w nowym oknie przeglądarki
ok. 2 min
Polecenie z arkusza
Zawartość bloku prawego: Animacja kalendarz.gif z tekstem alternatywnym „Kalendarz Majów”, której kliknięcie powoduje otwarcie strony internetowej https://pl.wikipedia.org/wiki/Kalendarz_Majów w nowym oknie przeglądarki.
Obraz wewnątrz <a>, target="_blank" - nowe okno (R.2.10, R.3.3). rel="noopener" odcina otwartej stronie dostęp do karty, z której przyszła (window.opener) - przy odnośnikach do obcych serwisów to standard. width i height rezerwują miejsce na obraz przed jego wczytaniem; ostateczną szerokość ustawi CSS.
R.2.5 Umieszczone w bloku nagłówkowym <h1>: "Dni, miesiące, lata…", w bloku środkowym <h2>: "Sprawdź kto ma urodziny", w bloku prawym <h2> "Rodzaje kalendarzy" oraz przynajmniej jeden paragraf
ok. 1 min
Polecenie z arkusza
Nagłówek drugiego stopnia o treści „Rodzaje kalendarzy”.
Krok 28: Lista numerowana z dwiema listami w środku
Kryteria:
R.2.9 W bloku prawym umieszczona jedna lista numerowana z dwoma elementami, każdy z nich zagnieżdża listę punktowaną, pierwsza podlista ma trzy elementy, druga dwa. Zastosowane znaczniki <ol>, <ul> i <li>, zagnieżdżenie wewnątrz znacznika <li>
ok. 3 min
Polecenie z arkusza
Lista numerowana (uporządkowana) z zagnieżdżonymi dwoma listami punktowanymi (nieuporządkowanymi), zgodna z ilustracją 5.
<ol> z dwoma <li>; w każdym, przed zamknięciem </li>, lista <ul> - to jest zagnieżdżenie (R.2.9).
Typowe błędy
<ul> wstawione między </li> a następne <li> przeglądarka pokaże podobnie, ale klucz wymaga zagnieżdżenia wewnątrz <li>.
R.2.5 Umieszczone w bloku nagłówkowym <h1>: "Dni, miesiące, lata…", w bloku środkowym <h2>: "Sprawdź kto ma urodziny", w bloku prawym <h2> "Rodzaje kalendarzy" oraz przynajmniej jeden paragraf
ok. 1 min
Polecenie z arkusza
Zawartość stopki: paragraf o treści „Stronę opracował(a): ”, dalej numer zdającego.
Akapit w <footer>. Na egzaminie po dwukropku wpisuje się swój numer zdającego (PESEL) - tutaj stoi imię i nazwisko autora rozwiązania.
R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z ilustracją 2 w arkuszu egzaminacyjnym (prawidłowo zastosowane właściwości CSS decydujące o układzie strony np. float i clear albo display flex albo grid albo position )
ok. 3 min
Polecenie z arkusza
Podział zrealizowany za pomocą semantycznych znaczników sekcji języka HTML5 tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z ilustracją 2.
Druga reguła dla body rysuje ilustrację 2 dosłownie:
grid-template-columns: 25% 40% 35% - szerokości trzech bloków z arkusza w jednej linii (klucz R.4.4 wymienia wprost grid-template-columns),
grid-template-areas - mapa strony wiersz po wierszu: nagłówek i blok napisu na całą szerokość, trzy bloki obok siebie, stopka,
grid-area przypisuje każdy blok do obszaru.
Wersja podstawowa robi to przez float: left trzech bloków i clear: both stopki. Tu nic nie „pływa”: stopka sama stoi pod blokami, a ich wysokości nie muszą się zgadzać (R.3.1).
R.4.2 Ustawiony kolor tła Indigo dla bloków nagłówkowego i stopki, BlueViolet dla bloku napisu, Lavender dla bloków lewego i prawego, GhostWhite dla środkowego
R.4.3 Ustawiony biały kolor czcionki dla bloku nagłówkowego i stopki
R.4.5 Ustawione wyrównanie tekstu do środka dla bloków nagłówkowego, środkowego i stopki oraz do prawej strony dla bloku napisu
R.4.6 Ustawione marginesy wewnętrzne (padding) 10px dla bloków nagłówkowego, napisu, stopki i obrazu, 3px dla komórek tabeli oraz ustawione marginesy zewnętrzne (margin) 30px dla tabeli i formularza
ok. 1 min
Polecenie z arkusza
Wspólne dla bloku nagłówkowego i stopki: kolor tła Indigo, biały kolor czcionki, marginesy wewnętrzne 10 px, wyrównanie tekstu do środka.
R.4.2 Ustawiony kolor tła Indigo dla bloków nagłówkowego i stopki, BlueViolet dla bloku napisu, Lavender dla bloków lewego i prawego, GhostWhite dla środkowego
R.4.5 Ustawione wyrównanie tekstu do środka dla bloków nagłówkowego, środkowego i stopki oraz do prawej strony dla bloku napisu
R.4.6 Ustawione marginesy wewnętrzne (padding) 10px dla bloków nagłówkowego, napisu, stopki i obrazu, 3px dla komórek tabeli oraz ustawione marginesy zewnętrzne (margin) 30px dla tabeli i formularza
ok. 1 min
Polecenie z arkusza
Dla bloku napisu: kolor tła BlueViolet, marginesy wewnętrzne 10 px, wyrównanie tekstu do prawej strony.
Krok 34: Bloki lewy i prawy, wysokość trzech bloków
Kryteria:
R.4.2 Ustawiony kolor tła Indigo dla bloków nagłówkowego i stopki, BlueViolet dla bloku napisu, Lavender dla bloków lewego i prawego, GhostWhite dla środkowego
ok. 1 min
Polecenie z arkusza
Wspólny dla bloków lewego i prawego: kolor tła Lavender, wysokość 500 px. Dodatkowo szerokość bloku lewego 25%, bloku prawego 35%.
Tło Lavender dla bloków bocznych, wysokość 500 px dla wszystkich trzech (środkowy ma ją w arkuszu osobno, a reguła z trzema selektorami zapisuje to raz). Szerokości są już w grid-template-columns - nie trzeba ich powtarzać w blokach.
R.4.2 Ustawiony kolor tła Indigo dla bloków nagłówkowego i stopki, BlueViolet dla bloku napisu, Lavender dla bloków lewego i prawego, GhostWhite dla środkowego
R.4.4 Ustawiona wysokość bloku lewego, środkowego i prawego 500px oraz szerokość bloku lewego 25%, środkowego 40%, prawego 35% (width lub grid-template-columns lub flex) oraz dla selektora img szerokość 50%
R.4.5 Ustawione wyrównanie tekstu do środka dla bloków nagłówkowego, środkowego i stopki oraz do prawej strony dla bloku napisu
ok. 1 min
Polecenie z arkusza
Dla bloku środkowego: kolor tła GhostWhite, wyrównanie tekstu do środka, wysokość 500 px, szerokość 40%.
Tło i wyśrodkowanie; wysokość i szerokość są już ustawione. Komplet wymiarów z klucza: wysokości 500 px i szerokości 25%, 40%, 35% (R.4.4).
R.4.4 Ustawiona wysokość bloku lewego, środkowego i prawego 500px oraz szerokość bloku lewego 25%, środkowego 40%, prawego 35% (width lub grid-template-columns lub flex) oraz dla selektora img szerokość 50%
R.4.6 Ustawione marginesy wewnętrzne (padding) 10px dla bloków nagłówkowego, napisu, stopki i obrazu, 3px dla komórek tabeli oraz ustawione marginesy zewnętrzne (margin) 30px dla tabeli i formularza
R.4.7 Ustawione dla obrazu opływanie tekstem po lewej stronie float:right
ok. 2 min
Polecenie z arkusza
Dla selektora obrazu: oblewanie tekstem po lewej stronie (obraz po prawej stronie), szerokość 50%, marginesy wewnętrzne 10 px.
Tu float: right zostaje: klucz R.4.7 wymaga go wprost, a opływanie tekstem to dokładnie to, do czego float powstał - nagłówek i lista stają obok obrazu. Siatka służy do układu bloków, float do obrazu w tekście. height: auto - obraz ma w HTML atrybut height, a przy szerokości 50% wysokość musi się liczyć z proporcji (R.4.4, R.4.6, R.4.7).
Selektor znacznika p (R.4.8). Dlatego wynik Skryptu 2 nie będzie akapitem: biały tekst na jasnym tle bloku środkowego byłby niewidoczny - na ilustracji 2 stoi zwykłym czarnym krojem.
R.4.6 Ustawione marginesy wewnętrzne (padding) 10px dla bloków nagłówkowego, napisu, stopki i obrazu, 3px dla komórek tabeli oraz ustawione marginesy zewnętrzne (margin) 30px dla tabeli i formularza
R.4.9 Ustawione dla tabeli i komórki tabeli obramowanie 1px solid Indigo
R.4.10 Ustawione dla tabeli obramowanie połączone border-collapse: collapse
ok. 3 min
Polecenie z arkusza
Wspólne dla tabeli i formularza: marginesy zewnętrzne 30 px. Dla tabeli i komórki tabeli: obramowanie połączone, linią ciągłą o szerokości 1 px i kolorze Indigo. Wspólne dla zwykłej komórki i komórki nagłówkowej tabeli: marginesy wewnętrzne 3 px.
table, form - margines 30 px (R.4.6),
table, td - ramka i border-collapse: collapse (R.4.9, R.4.10); komórki nagłówkowe <th> nie mają własnych ramek, więc wiersz nagłówka zostaje bez linii między „liczba dni” a „miesiąc” - jak na ilustracji 3,
Kroki 39-46 · po tym etapie masz 43 z 43 kryteriów (pkt)
Krok 39: Połączenie PDO na górze pliku i jego zamknięcie
Kryteria: ,
R.5.1 Skrypt jest napisany w języku PHP i zawiera przynajmniej jedną zgodną z treścią zadania instrukcję
R.5.2 Skrypt realizuje połączenie z serwerem bazy danych i wybór bazy kalendarz oraz ostatnią operacją na bazie jest jej zamknięcie
ok. 3 min
Polecenie z arkusza
Łączą się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie kalendarz. Na końcu zamykane jest połączenie z serwerem.
Cała praca z bazą trafia przed<!DOCTYPE html>: najpierw dane, potem HTML, który je tylko wypisuje.
new PDO(...) łączy się z serwerem i wybiera bazę kalendarz w jednym napisie (DSN); charset=utf8mb4 ustawia kodowanie połączenia (R.5.1, R.5.2),
ERRMODE_EXCEPTION - każdy błąd bazy rzuca wyjątek zamiast po cichu zwracać false,
$pdo = null zamyka połączenie - to będzie ostatnia operacja na bazie, przed HTML-em (R.5.2),
try/catch (PDOException) łapie awarię bazy; szczegóły trafiają do dziennika serwera (error_log), a nie na stronę - komunikat dla odwiedzającego dojdzie w Skrypcie 1.
Podgląd od tego kroku to wynik prawdziwego uruchomienia strony w PHP 8.2.
R.5.4 Skrypt 1 pobiera bieżący dzień tygodnia lub numer dnia tygodnia i przekształca go na dzień tygodnia zapisany w języku polskim
ok. 3 min
Polecenie z arkusza
Wyświetla tekst o treści „Dzisiaj jest <dzień tygodnia>, <data>, imieniny: <imiona>”, gdzie <dzień tygodnia> oznacza słowny zapis bieżącego dnia w języku polskim, np. „poniedziałek”.
const DAYS - stała z nazwami dni od poniedziałku; stała, bo ta lista się nie zmienia,
new DateTimeImmutable() - obiekt z bieżącą datą i godziną; „immutable” znaczy, że żadna metoda go nie zmienia, tylko zwraca nowy obiekt,
$today->format('N') - numer dnia od 1 (poniedziałek) do 7 (niedziela), a indeksy tablicy liczą się od 0, stąd - 1 (R.5.4).
W podglądzie „dzisiaj” to czwartek 25 maja 2023 - dzień z ilustracji 2.
Typowe błędy
format('w') numeruje dni od niedzieli (0) - z tablicą od poniedziałku każdy dzień przesunie się o jeden.
Krok 41: Skrypt 1: dzisiejsza data w dwóch formatach
Kryteria:
R.5.5 Skrypt 1 ustala bieżącą datę w formacie mm-dd oraz dd-mm-yy, np. $data = date("m-d"); $dataPelna = date("d-m-Y");
ok. 2 min
Polecenie z arkusza
Wysyła do bazy danych zmodyfikowane zapytanie 2, tak że jest sprawdzana data bieżąca w formacie mm-dd. <data> oznacza bieżącą datę w formacie dd-mm-yyyy.
Ten sam obiekt, dwa formaty: format('m-d') daje 05-25 - format pola data w bazie, a format('d-m-Y') - 25-05-2023 do wyświetlenia (R.5.5). Litery formatu są te same co w funkcji date() z ramki arkusza.
R.5.3 Przynajmniej jeden skrypt zawiera instrukcję wysyłającą do bazy danych zmodyfikowane zapytanie 2 (wstawiona data z formularza lub bieżąca data)
ok. 3 min
Polecenie z arkusza
Wysyła do bazy danych zmodyfikowane zapytanie 2, tak że jest sprawdzana data bieżąca w formacie mm-dd.
Oba skrypty wykonują to samo zapytanie 2, tylko z inną datą - więc jest jedna funkcjanamesForDay(PDO $pdo, string $monthDay): string:
prepare z parametrem nazwanym :day w miejscu daty - treść zapytania jest stała,
execute(['day' => $monthDay]) wysyła datę osobno; baza nie potraktuje jej jako fragmentu SQL, cokolwiek by zawierała,
fetchColumn() zwraca pierwszą kolumnę pierwszego wiersza, czyli imiona; gdy wiersza nie ma - false, a ?: podstawia wtedy „brak danych”.
Deklaracje typów (PDO, string) pilnują, żeby funkcji nie dało się wywołać z czymś innym. W try Skrypt 1 woła ją z dzisiejszą datą $todayMonthDay (R.5.3).
R.5.8 Skrypt 1 wyświetla w bloku napisu treść "Dzisiaj jest <dzień tygodnia>, <data>, imieniny: <imiona>”, gdzie <dzień tygodnia> oznacza dowolny słowny zapis bieżącego dnia, <data> oznacza bieżącą datę w formacie dd-mm-yyyy, a <imiona> - pole zwrócone zapytaniem
R.5.10 W skryptach zastosowana przynajmniej jedna zmienna lub funkcja oraz nazwy wszystkich funkcji i zmiennych są w języku polskim lub angielskim i odzwierciedlają cel zastosowania
ok. 3 min
Polecenie z arkusza
Wyświetla tekst o treści „Dzisiaj jest <dzień tygodnia>, <data>, imieniny: <imiona>”, gdzie <imiona> oznacza pole zwrócone zapytaniem.
$todayText dostaje najpierw komunikat awaryjny, a w try - gotowe zdanie. Gdy baza nie działa, strona pokaże „Nie udało się odczytać imienin z bazy.” zamiast białego ekranu z błędem,
funkcja e() to skrót od htmlspecialchars(..., ENT_QUOTES, 'UTF-8'): znaki <, >, & i cudzysłowy zamienia na encje, więc nic z bazy nie zostanie potraktowane jak HTML,
w bloku napisu <?= e($todayText) ?> - <?= to krótki zapis <?php echo.
Podgląd: „Dzisiaj jest czwartek, 25-05-2023, imieniny: Grzegorza, Urbana, Magdaleny” - jak na ilustracji 2 (R.5.8, R.5.10).
R.5.6 Skrypt 2 zawiera instrukcję pobierającą dane z tablicy globalnej odpowiadającej zastosowanej metodzie formularza ($_POST, $_GET, $_REQUEST)
ok. 2 min
Polecenie z arkusza
Pobiera datę z formularza, a następnie przekształca ją do formatu mm-dd.
$_POST['date'] ?? null - operator ?? daje null, gdy formularz nie był wysłany (pierwsze wejście na stronę), bez ostrzeżenia „Undefined array key” (R.5.6).
Klucz R.5.6 wymaga instrukcji pobierającej dane z tablicy globalnej ($_POST), dlatego nie ma tu filter_input(INPUT_POST, 'date'), które w prawdziwym projekcie byłoby równie dobrym wyborem - robi to samo, ale nie dotyka tablicy $_POST w kodzie.
Krok 45: Skrypt 2: sprawdzenie daty i format mm-dd
Kryteria:
R.5.7 Skrypt 2 ustala datę z formatu pola edycyjnego na format w bazie mm-dd , np. $dataDoZapytania = date("m-d", strtotime($dzien));
ok. 4 min
Polecenie z arkusza
Pobiera datę z formularza, a następnie przekształca ją do formatu mm-dd.
DateTimeImmutable::createFromFormat('!Y-m-d', $dateText) odczytuje datę tylko w formacie z pola daty (2024-01-24); ! zeruje godzinę. Potem trzy warunki:
odczyt się udał,
data zapisana z powrotem jest identyczna z wysłaną - 2024-02-31 PHP przeliczyłby na 2 marca, a porównanie to wyłapie,
rok to 2024, jak w min i max pola.
Inaczej $dateError z komunikatem. is_string odsiewa przypadek, w którym ktoś wyśle date[]=... (tablicę zamiast napisu). Format bazy da potem $selectedDate->format('m-d') (R.5.7).
Wersja podstawowa używa strtotime, które nie odrzuca dat nieistniejących - dla 2024-02-31 pokazuje imieniny z 2 marca.
R.5.3 Przynajmniej jeden skrypt zawiera instrukcję wysyłającą do bazy danych zmodyfikowane zapytanie 2 (wstawiona data z formularza lub bieżąca data)
R.5.9 Skrypt 2 wyświetla pod formularzem treść: "Dnia <data> są imieniny: <imiona>", gdzie <data> oznacza datę pobraną z formularza w formacie yyyy-mm-dd, <imiona> - pole zwrócone zapytaniem
R.5.10 W skryptach zastosowana przynajmniej jedna zmienna lub funkcja oraz nazwy wszystkich funkcji i zmiennych są w języku polskim lub angielskim i odzwierciedlają cel zastosowania
ok. 3 min
Polecenie z arkusza
Wysyła do bazy danych zmodyfikowane zapytanie 2, tak, że jest sprawdzana data podana w formularzu w formacie mm-dd. Wyświetla tekst o treści „Dnia <data> są imieniny: <imiona>”, gdzie <data> oznacza datę pobraną z formularza w formacie yyyy-mm-dd, <imiona> - pole zwrócone zapytaniem.
w try, przed$pdo = null: jeśli data jest poprawna, ta sama funkcja namesForDay z datą z formularza (R.5.3),
pod formularzem if / elseif / endif w składni dla szablonów: wynik, komunikat o złej dacie albo nic (pierwsze wejście). Data wypisana tak, jak przyszła (rrrr-mm-dd) - przez e(), bo pochodzi od użytkownika,
wynik w <div>, nie w <p> - styl akapitów zrobiłby go białym na jasnym tle,
pole daty dostaje value z wysłaną datą: po wysłaniu formularz pamięta wybór.
Podgląd po wysłaniu 24 stycznia 2024: „Dnia 2024-01-24 są imieniny: Felicji, Franciszka, Rafała” - jak na ilustracji 2 (R.5.9, R.5.10).
Kroki 47-48 · po tym etapie masz 43 z 43 kryteriów (pkt)
Krok 47: Co jest inaczej i dlaczego
ok. 3 min
Polecenie z arkusza
Ocenie podlegać będzie 5 rezultatów: operacje na bazie danych, zawartość witryny internetowej, działanie witryny internetowej, styl CSS witryny internetowej oraz skrypt połączenia z bazą.
Obie wersje dają te same punkty. Różnice:
wersja podstawowa
ta wersja
układ
float: left i clear: both
grid-template-areas, szerokości w grid-template-columns
kolory
wpisane w regułach
zmienne w :root
baza
mysqli_* z tabeli 1
PDO, wyjątki, połączenie zamknięte przed HTML-em
zapytanie
data wklejona w napis zapytania, dwa razy
jedna funkcja z zapytaniem przygotowanym
data
date(), strtotime
DateTimeImmutable, createFromFormat
2024-02-31
imieniny z 2 marca
„Podaj poprawną datę z 2024 roku.”
awaria bazy
błąd PHP w połowie strony
komunikat w bloku napisu, szczegóły w dzienniku
wypisywanie
echo danych wprost
e() przy każdym wypisaniu
Sprawdzone w PHP 8.2 na bazie z arkusza: data z ilustracji, 31 grudnia, 31 lutego, data z 2023 roku, zły format, kod HTML w polu daty, pierwsze wejście bez formularza i wyłączona baza.
Czas przeznaczony na wykonanie zadania wynosi 150 minut.
Wersja podstawowa, gdy liczy się czas: funkcje mysqli_* są w tabeli 1 arkusza, a date() i strtotime w ramce z funkcjami daty.
Ta wersja, gdy PDO i DateTimeImmutable pisze się z pamięci - na egzaminie nie ma dokumentacji, a arkusz ich nie podpowiada.
Mieszanie daje pełne punkty: siatka z tej wersji i skrypty z podstawowej. Jedna rzecz warta przeniesienia zawsze: ?? null przy odczycie $_POST - jedna linia mniej ostrzeżeń przy pierwszym wejściu na stronę.
Krok 49 · po tym etapie masz 43 z 43 kryteriów (pkt)
Krok 49: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
Po zakończeniu pracy utwórz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowana była poprawność działania witryny. Nagraj płytę z rezultatami pracy.
W przeglądarka.txt nazwa przeglądarki, w której strona była sprawdzana przez http://localhost/….
W folderze z numerem zdającego: imieniny.csv, import.png, kalendarz.gif, kalendarz.php, kw1.png - kw4.png, kwerendy.txt, parametry_animacji.png, przeglądarka.txt i styl.css. Po nagraniu trzeba sprawdzić odczyt płyty 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.