Przejdź do głównej treści
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.

  1. 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.

  2. 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.

  3. 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).

  4. 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.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT data
    FROM imieniny
    WHERE imiona LIKE '%Karola%';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. 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.txt Tekst zmienione: 5 linii
    -- Zapytanie 1
    SELECT data
    FROM imieniny
    WHERE imiona LIKE '%Karola%';
    
    -- Zapytanie 2
    SELECT imiona
    FROM imieniny
    WHERE data = '05-04';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. 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.txt Tekst zmienione: 5 linii
    -- Zapytanie 1
    SELECT data
    FROM imieniny
    WHERE imiona LIKE '%Karola%';
    
    -- Zapytanie 2
    SELECT imiona
    FROM imieniny
    WHERE data = '05-04';
    
    -- Zapytanie 3
    SELECT COUNT(*) AS liczba_dat
    FROM imieniny
    WHERE imiona LIKE '%mir%';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. 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.txt Tekst zmienione: 4 linie
    -- Zapytanie 1
    SELECT data
    FROM imieniny
    WHERE imiona LIKE '%Karola%';
    
    -- Zapytanie 2
    SELECT imiona
    FROM imieniny
    WHERE data = '05-04';
    
    -- Zapytanie 3
    SELECT COUNT(*) AS liczba_dat
    FROM imieniny
    WHERE imiona LIKE '%mir%';
    
    -- Zapytanie 4
    ALTER TABLE imieniny
    ADD COLUMN zyczenia VARCHAR(500);
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. 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.

    imieniny.csv CSV nowy plik
    "1","01-01","Mieszka, Mieczysława, Marii",NULL
    "2","01-02","Izydora, Bazylego, Grzegorza",NULL
    "3","01-03","Arlety, Genowefy, Danuty",NULL
    "4","01-04","Tytusa, Anieli, Eugeniusza",NULL
    "5","01-05","Hanny, Szymona, Edwarda",NULL
    "6","01-06","Kacpra, Melchiora, Baltazara",NULL
    "7","01-07","Juliana, Lucjana, Rajmunda",NULL
    "8","01-08","Seweryna, Mścisława, Juliusza",NULL
    "9","01-09","Marceliny, Marianny, Juliana",NULL
    "10","01-10","Wilhelma, Dobrosława, Danuty",NULL
    "11","01-11","Honoraty, Teodozjusza, Matyldy",NULL
    "12","01-12","Grety, Arkadiusza, Rajmunda",NULL
    "13","01-13","Bogumiły, Weroniki, Hilarego",NULL
    "14","01-14","Feliksa, Domosława, Niny",NULL
    "15","01-15","Pawła, Arnolda, Izydora",NULL
    "16","01-16","Marcelego, Włodzimierza, Waldemara",NULL
    "17","01-17","Antoniego, Rościsława, Jana",NULL
    "18","01-18","Piotra, Małgorzaty",NULL
    "19","01-19","Henryka, Mariusza, Marty",NULL
    "20","01-20","Fabiana, Sebastiana",NULL
    "21","01-21","Agnieszki, Jarosława",NULL
    "22","01-22","Anastazego, Wincentego",NULL
    "23","01-23","Ildefonsa, Rajmunda",NULL
    "24","01-24","Felicji, Franciszka, Rafała",NULL
    "25","01-25","Pawła, Miłosza, Elwiry",NULL
    "26","01-26","Tymoteusza, Michała, Tytusa",NULL
    "27","01-27","Przybysława, Anieli, Jerzego",NULL
    "28","01-28","Walerego, Radomira, Tomasza",NULL
    "29","01-29","Zdzisława, Franciszka, Józefa",NULL
    "30","01-30","Macieja, Martyny, Teofila",NULL
    "31","01-31","Marceli, Ludwiki, Jana",NULL
    "32","02-01","Brygidy, Ignacego, Seweryna",NULL
    "33","02-02","Marii, Miłosława",NULL
    "34","02-03","Błażeja, Oskara",NULL
    "35","02-04","Andrzeja, Weroniki, Joanny",NULL
    "36","02-05","Agaty, Adelajdy",NULL
    "37","02-06","Doroty, Bogdana, Pawła",NULL
    "38","02-07","Ryszarda, Teodora, Romana",NULL
    "39","02-08","Hieronima, Sebastiana, Ireny",NULL
    "40","02-09","Apolonii, Eryki, Cyryla",NULL
    "41","02-10","Elwiry, Jacka, Scholastyki",NULL
    "42","02-11","Lucjana, Olgierda",NULL
    "43","02-12","Eulalii, Radosława, Modesta",NULL
    "44","02-13","Grzegorza, Katarzyny",NULL
    "45","02-14","Cyryla, Metodego, Walentego",NULL
    "46","02-15","Jowity, Faustyna, Zygfryda",NULL
    "47","02-16","Danuty, Julianny, Daniela",NULL
    "48","02-17","Aleksego, Zbigniewa, Łukasza",NULL
    "49","02-18","Szymona, Konstancji, Flawiana",NULL
    "50","02-19","Arnolda, Konrada, Marcelego",NULL
    "51","02-20","Leona, Ludomira, Zenobiusza",NULL
    "52","02-21","Eleonory, Fortunata, Roberta",NULL
    "53","02-22","Marty, Małgorzaty, Piotra",NULL
    "54","02-23","Romany, Damiana, Polikarpa",NULL
    "55","02-24","Macieja, Bogusza, Sergiusza",NULL
    "56","02-25","Wiktora, Cezarego",NULL
    "57","02-26","Mirosława, Aleksandra",NULL
    "58","02-27","Gabriela, Anastazji",NULL
    "59","02-28","Romana, Ludomira, Lecha",NULL
    "60","02-29","Lecha, Lutosława",NULL
    "61","03-01","Antoniny, Radosława, Dawida",NULL
    "62","03-02","Heleny, Halszki, Pawła",NULL
    "63","03-03","Maryny, Kunegundy, Tycjana",NULL
    "64","03-04","Lucji, Kazimierza, Eugeniusza",NULL
    "65","03-05","Adriana, Fryderyka, Teofila",NULL
    "66","03-06","Róży, Jordana, Agnieszki",NULL
    "67","03-07","Tomasza, Perpetuy, Felicyty",NULL
    "68","03-08","Beaty, Wincentego, Jana",NULL
    "69","03-09","Franciszki, Brunona",NULL
    "70","03-10","Cypriana, Marcela, Aleksandra",NULL
    "71","03-11","Ludosława, Konstantyna, Benedykta",NULL
    "72","03-12","Grzegorza, Justyna, Alojzego",NULL
    "73","03-13","Bożeny, Krystyny",NULL
    "74","03-14","Leona, Matyldy, Łazarza",NULL
    "75","03-16","Longina, Klemensa, Ludwiki",NULL
    "76","03-16","Izabeli, Oktawii, Hilarego",NULL
    "77","03-17","Patryka, Zbigniewa, Gertrudy",NULL
    "78","03-18","Cyryla, Edwarda, Boguchwały",NULL
    "79","03-19","Józefa, Bogdana",NULL
    "80","03-20","Klaudii, Eufemii, Maurycego",NULL
    "81","03-21","Lubomira, Benedykta",NULL
    "82","03-22","Katarzyny, Bogusława",NULL
    "83","03-23","Pelagii, Oktawiana, Feliksa",NULL
    "84","03-24","Marka, Gabriela, Katarzyny",NULL
    "85","03-25","Marioli, Wieńczysława, Ireneusza",NULL
    "86","03-26","Larysy, Emmanuela, Teodora",NULL
    "87","03-27","Lidii, Ernesta",NULL
    "88","03-28","Anieli, Sykstusa, Jana",NULL
    "89","03-29","Wiktoryna, Helmuta, Eustachego",NULL
    "90","03-30","Anieli, Kwiryna, Leonarda",NULL
    "91","03-31","Beniamina, Dobromierza, Leonarda",NULL
    "92","04-01","Teodory, Grażyny, Ireny",NULL
    "93","04-02","Władysława, Franciszka, Teodozji",NULL
    "94","04-03","Ryszarda, Pankracego, Ingi",NULL
    "95","04-04","Izydora, Wacława",NULL
    "96","04-05","Ireny, Wincentego",NULL
    "97","04-06","Izoldy, Celestyna, Wilhelma",NULL
    "98","04-07","Rufina, Celestyna, Jana",NULL
    "99","04-08","Cezaryny, Dionizego, Julii",NULL
    "100","04-09","Marii, Dymitra, Heliodora",NULL
    "101","04-10","Michała, Makarego",NULL
    "102","04-11","Filipa, Leona",NULL
    "103","04-12","Juliusza, Lubosława, Zenona",NULL
    "104","04-13","Przemysława, Hermenegildy, Marcina",NULL
    "105","04-14","Bereniki, Waleriana, Justyny",NULL
    "106","04-15","Ludwiny, Wacławy, Anastazji",NULL
    "107","04-16","Kseni, Cecylii, Bernadety",NULL
    "108","04-17","Rudolfa, Roberta",NULL
    "109","04-18","Bogusławy, Apoloniusza",NULL
    "110","04-19","Adolfa, Tymona, Leona",NULL
    "111","04-20","Czesława, Agnieszki, Mariana",NULL
    "112","04-21","Anzelma, Bartosza, Feliksa",NULL
    "113","04-22","Kai, Leonii, Sotera",NULL
    "114","04-23","Jerzego, Wojciecha",NULL
    "115","04-24","Horacego, Feliksa, Grzegorza",NULL
    "116","04-25","Marka, Jarosława, Wasyla",NULL
    "117","04-26","Marzeny, Klaudiusza, Marii",NULL
    "118","04-27","Zyty, Teofila, Felicji",NULL
    "119","04-28","Piotra, Walerii, Witalisa",NULL
    "120","04-29","Rity, Katarzyny, Bogusława",NULL
    "121","04-30","Mariana, Donaty, Tamary",NULL
    "122","05-01","Józefa, Jeremiasza, Filipa",NULL
    "123","05-02","Zygmunta, Atanazego, Anatola",NULL
    "124","05-03","Marii, Antoniny",NULL
    "125","05-04","Moniki, Floriana, Władysława",NULL
    "126","05-05","Ireny, Waldemara",NULL
    "127","05-06","Judyty, Jakuba, Filipa",NULL
    "128","05-07","Gizeli, Ludmiły, Benedykta",NULL
    "129","05-08","Stanisława, Lizy, Wiktora",NULL
    "130","05-09","Bożydara, Grzegorza, Karoliny",NULL
    "131","05-10","Izydora, Antoniny, Symeona",NULL
    "132","05-11","Igi, Miry, Władysławy",NULL
    "133","05-12","Pankracego, Dominika, Achillesa",NULL
    "134","05-13","Serwacego, Roberta, Glorii",NULL
    "135","05-14","Bonifacego, Dobiesława, Macieja",NULL
    "136","05-15","Zofii, Nadziei, Izydora",NULL
    "137","05-16","Andrzeja, Jędrzeja, Szymona",NULL
    "138","05-17","Paschalisa, Sławomira, Weroniki",NULL
    "139","05-18","Eryka, Feliksa, Jana",NULL
    "140","05-19","Iwa, Piotra, Celestyna",NULL
    "141","05-20","Bazylego, Bernardyna, Aleksandra",NULL
    "142","05-21","Wiktora, Kryspina, Tymoteusza",NULL
    "143","05-22","Heleny, Wiesławy, Ryty",NULL
    "144","05-23","Iwony, Dezyderego, Kryspina",NULL
    "145","05-24","Joanny, Zuzanny",NULL
    "146","05-25","Grzegorza, Urbana, Magdaleny",NULL
    "147","05-26","Filipa, Pauliny",NULL
    "148","05-27","Augustyna, Juliana, Magdaleny",NULL
    "149","05-28","Jaromira, Justa, Justyny",NULL
    "150","05-29","Magdaleny, Bogumiły, Urszuli",NULL
    "151","05-30","Ferdynanda, Karola, Jana",NULL
    "152","05-31","Anieli, Petroneli",NULL
    "153","06-01","Justyna, Anieli, Konrada",NULL
    "154","06-02","Marianny, Marcelina, Piotra",NULL
    "155","06-03","Leszka, Tamary, Karola",NULL
    "156","06-04","Kwiryny, Franciszka",NULL
    "157","06-05","Waltera, Bonifacego, Walerii",NULL
    "158","06-06","Norberta, Laurentego, Bogumiła",NULL
    "159","06-07","Roberta, Wiesława",NULL
    "160","06-08","Medarda, Maksyma, Seweryna",NULL
    "161","06-09","Pelagii, Dominika, Efrema",NULL
    "162","06-10","Bogumiła, Małgorzaty, Diany",NULL
    "163","06-11","Barnaby, Radomiła, Feliksa",NULL
    "164","06-12","Janiny, Onufrego, Leona",NULL
    "165","06-13","Lucjana, Antoniego",NULL
    "166","06-14","Bazylego, Elwiry, Michała",NULL
    "167","06-15","Wita, Jolanty",NULL
    "168","06-16","Aliny, Benona, Anety",NULL
    "169","06-17","Laury, Marcjana, Alberta",NULL
    "170","06-18","Marka, Elżbiety",NULL
    "171","06-19","Gerwazego, Protazego",NULL
    "172","06-20","Diny, Bogny, Florentyny",NULL
    "173","06-21","Alicji, Alojzego",NULL
    "174","06-22","Pauliny, Tomasza, Jana",NULL
    "175","06-23","Wandy, Zenona",NULL
    "176","06-24","Jana, Danuty",NULL
    "177","06-25","Lucji, Wilhelma, Doroty",NULL
    "178","06-26","Jana, Pawła",NULL
    "179","06-27","Maryli, Władysława, Cyryla",NULL
    "180","06-28","Leona, Ireneusza",NULL
    "181","06-29","Piotra, Pawła",NULL
    "182","06-30","Emilii, Lucyny",NULL
    "183","07-01","Haliny, Mariana, Marcina",NULL
    "184","07-02","Jagody, Urbana, Marii",NULL
    "185","07-03","Jacka, Anatola, Tomasza",NULL
    "186","07-04","Odona, Malwiny, Elżbiety",NULL
    "187","07-05","Marii, Antoniego",NULL
    "188","07-06","Gotarda, Dominiki, Lucji",NULL
    "189","07-07","Cyryla, Estery, Metodego",NULL
    "190","07-08","Edgara, Elżbiety, Eugeniusza",NULL
    "191","07-09","Lukrecji, Weroniki, Zenona",NULL
    "192","07-10","Sylwany, Witalisa, Antoniego",NULL
    "193","07-11","Olgi, Kaliny, Benedykta",NULL
    "194","07-12","Jana, Brunona, Bonifacego",NULL
    "195","07-13","Henryka, Kingi, Andrzeja",NULL
    "196","07-14","Ulryka, Bonawentury, Kamila",NULL
    "197","07-15","Henryka, Włodzimierza, Dawida",NULL
    "198","07-16","Mariki, Benity, Eustachego",NULL
    "199","07-17","Anety, Bogdana, Jadwigi",NULL
    "200","07-18","Erwina, Kamila, Szymona",NULL
    "201","07-19","Wincentego, Wodzisława, Marcina",NULL
    "202","07-20","Czesława, Hieronima, Małgorzaty",NULL
    "203","07-21","Daniela, Diany, Wawrzyńca",NULL
    "204","07-22","Marii, Magdaleny",NULL
    "205","07-23","Stwosza, Bogny, Brygidy",NULL
    "206","07-24","Kingi, Krystyny",NULL
    "207","07-25","Walentyny, Krzysztofa, Jakuba",NULL
    "208","07-26","Anny, Mirosławy, Grażyny",NULL
    "209","07-27","Lilii, Julii, Natalii",NULL
    "210","07-28","Aidy, Marceli, Wiktora",NULL
    "211","07-29","Olafa, Marty, Ludmiły",NULL
    "212","07-30","Julity, Piotra, Aldony",NULL
    "213","07-31","Ignacego, Lubomira, Heleny",NULL
    "214","08-01","Nadii, Justyna, Juliana",NULL
    "215","08-02","Kariny, Gustawa, Euzebiusza",NULL
    "216","08-03","Lidii, Augusta, Nikodema",NULL
    "217","08-04","Dominika, Protazego, Jana",NULL
    "218","08-05","Oswalda, Marii, Mariana",NULL
    "219","08-06","Sławy, Jakuba, Oktawiana",NULL
    "220","08-07","Kajetana, Doroty, Sykstusa",NULL
    "221","08-08","Cypriana, Emiliana, Dominika",NULL
    "222","08-09","Romana, Ryszarda, Edyty",NULL
    "223","08-10","Borysa, Filomeny, Wawrzyńca",NULL
    "224","08-11","Klary, Zuzanny, Lecha",NULL
    "225","08-12","Innocentego, Lecha, Euzebii",NULL
    "226","08-13","Diany, Hipolita",NULL
    "227","08-14","Alfreda, Euzebiusza, Maksymiliana",NULL
    "228","08-15","Napoleona, Stelli",NULL
    "229","08-16","Rocha, Stefana, Joachima",NULL
    "230","08-17","Mirona, Jacka",NULL
    "231","08-18","Ilony, Bronisława, Heleny",NULL
    "232","08-19","Bolesława, Juliana",NULL
    "233","08-20","Bernarda, Samuela, Sobiesława",NULL
    "234","08-21","Joanny, Kazimiery, Piusa",NULL
    "235","08-22","Cezarego, Tymoteusza",NULL
    "236","08-23","Apolinarego, Filipa",NULL
    "237","08-24","Jerzego, Bartosza, Haliny",NULL
    "238","08-25","Luizy, Ludwika, Józefa",NULL
    "239","08-26","Marii, Aleksandra",NULL
    "240","08-27","Cezarego, Józefa, Moniki",NULL
    "241","08-28","Patrycji, Wyszomira, Augustyna",NULL
    "242","08-29","Beaty, Jana, Sabiny, Racibora",NULL
    "243","08-30","Róży, Szczęsnego, Feliksa",NULL
    "244","08-31","Bogdana, Ramony, Rajmunda",NULL
    "245","09-01","Idziego, Bronisława",NULL
    "246","09-02","Juliana, Stefana, Wilhelma",NULL
    "247","09-03","Grzegorza, Izabeli, Szymona",NULL
    "248","09-04","Idy, Julianny, Rozalii, Róży",NULL
    "249","09-05","Doroty, Teodora, Wawrzyńca",NULL
    "250","09-06","Beaty, Eugeniusza",NULL
    "251","09-07","Domosławy, Melchiora, Reginy",NULL
    "252","09-08","Marii, Adrianny, Serafiny",NULL
    "253","09-09","¦cibora, Sergiusza, Piotra",NULL
    "254","09-10","Łukasza, Aldony, Mścisława",NULL
    "255","09-11","Jacka, Prota, Dagny, Hiacynta",NULL
    "256","09-12","Gwidona, Radzimira, Marii",NULL
    "257","09-13","Eugenii, Aureliusza, Jana",NULL
    "258","09-14","Roksany, Bernarda, Cypriana",NULL
    "259","09-15","Albina, Nikodema, Marii",NULL
    "260","09-16","Edyty, Korneliusza, Cypriana",NULL
    "261","09-17","Franciszka, Roberta, Justyna",NULL
    "262","09-18","Irmy, Stanisława, Ireny",NULL
    "263","09-19","Januarego, Konstancji, Teodora",NULL
    "264","09-20","Filipiny, Eustachego, Euzebii",NULL
    "265","09-21","Jonasza, Mateusza, Hipolita",NULL
    "266","09-22","Tomasza, Maurycego, Joachima",NULL
    "267","09-23","Tekli, Bogusława, Linusa",NULL
    "268","09-24","Gerarda, Ruperta, Tomiry",NULL
    "269","09-25","Aurelii, Władysława, Kleofasa",NULL
    "270","09-26","Wawrzyńca, Kosmy, Damiana",NULL
    "271","09-27","Wincentego, Mirabeli, Justyny",NULL
    "272","09-28","Wacława, Tymona, Marka",NULL
    "273","09-29","Michała, Gabriela, Rafała",NULL
    "274","09-30","Wery, Honoriusza, Hieronima",NULL
    "275","10-01","Danuty, Remigiusza, Teresy",NULL
    "276","10-02","Teofila, Dionizego, Sławomira",NULL
    "277","10-03","Teresy, Heliodora, Jana",NULL
    "278","10-04","Rozalii, Edwina, Franciszka",NULL
    "279","10-05","Placyda, Apolinarego",NULL
    "280","10-06","Artura, Brunona",NULL
    "281","10-07","Marii, Marka, Mirelli",NULL
    "282","10-08","Pelagii, Brygidy, Walerii",NULL
    "283","10-09","Arnolda, Dionizego, Wincentego",NULL
    "284","10-10","Pauliny, Danieli, Leona",NULL
    "285","10-11","Aldony, Aleksandra, Dobromiry",NULL
    "286","10-12","Eustachego, Maksymiliana, Edwina",NULL
    "287","10-13","Geralda, Edwarda, Honorata",NULL
    "288","10-14","Liwii, Kaliksta, Bernarda",NULL
    "289","10-15","Jadwigi, Teresy, Florentyny",NULL
    "290","10-16","Gawła, Ambrożego",NULL
    "291","10-17","Wiktora, Marity, Ignacego",NULL
    "292","10-18","Juliana, Łukasza",NULL
    "293","10-19","Ziemowita, Jana, Pawła",NULL
    "294","10-20","Ireny, Kleopatry, Jana",NULL
    "295","10-21","Urszuli, Hilarego, Jakuba",NULL
    "296","10-22","Halki, Filipa, Salomei",NULL
    "297","10-23","Marleny, Seweryna, Igi",NULL
    "298","10-24","Rafała, Marcina, Antoniego",NULL
    "299","10-25","Darii, Wilhelminy, Bonifacego",NULL
    "300","10-26","Lucjana, Ewarysta, Damiana",NULL
    "301","10-27","Iwony, Sabiny",NULL
    "302","10-28","Szymona, Tadeusza",NULL
    "303","10-29","Euzebii, Wioletty, Felicjana",NULL
    "304","10-30","Zenobii, Przemysława, Edmunda",NULL
    "305","10-31","Urbana, Saturnina, Krzysztofa",NULL
    "306","11-01","Seweryna, Wiktoryny",NULL
    "307","11-02","Bohdany, Bożydara",NULL
    "308","11-03","Sylwii, Marcina, Huberta",NULL
    "309","11-04","Karola, Olgierda",NULL
    "310","11-05","Elżbiety, Sławomira, Dominika",NULL
    "311","11-06","Feliksa, Leonarda, Ziemowita",NULL
    "312","11-07","Antoniego, Żytomira, Ernesta",NULL
    "313","11-08","Seweryna, Bogdana, Klaudiusza",NULL
    "314","11-09","Aleksandra, Ludwika, Teodora",NULL
    "315","11-10","Leny, Ludomira, Leona",NULL
    "316","11-11","Marcina, Bartłomieja, Teodora",NULL
    "317","11-12","Renaty, Witolda, Jozafata",NULL
    "318","11-13","Mateusza, Izaaka, Stanisława",NULL
    "319","11-14","Rogera, Serafina, Wawrzyńca",NULL
    "320","11-15","Alberta, Leopolda",NULL
    "321","11-16","Gertrudy, Edmunda, Marii",NULL
    "322","11-17","Salomei, Grzegorza, Elżbiety",NULL
    "323","11-18","Romana, Klaudyny, Karoliny",NULL
    "324","11-19","Seweryny, Maksyma, Salomei",NULL
    "325","11-20","Anatola, Sędzimira, Rafała",NULL
    "326","11-21","Alberta, Janusza, Konrada",NULL
    "327","11-22","Cecylii, Wszemiły, Stefana",NULL
    "328","11-23","Adeli, Klemensa, Felicyty",NULL
    "329","11-24","Flory, Emmy, Chryzogona",NULL
    "330","11-25","Erazma, Katarzyny",NULL
    "331","11-26","Delfiny, Sylwestra, Konrada",NULL
    "332","11-27","Waleriana, Wirgiliusza, Maksyma",NULL
    "333","11-28","Lesława, Zdzisława, Stefana",NULL
    "334","11-29","Błażeja, Saturnina",NULL
    "335","11-30","Andrzeja, Maury, Konstantego",NULL
    "336","12-01","Natalii, Eligiusza, Edmunda",NULL
    "337","12-02","Balbiny, Bibianny, Pauliny",NULL
    "338","12-03","Franciszka, Ksawerego, Kasjana",NULL
    "339","12-04","Barbary, Krystiana, Jana",NULL
    "340","12-05","Sabiny, Krystyny, Edyty",NULL
    "341","12-06","Mikołaja, Jaremy, Emiliana",NULL
    "342","12-07","Marcina, Ambrożego, Teodora",NULL
    "343","12-08","Marii, Światozara, Makarego",NULL
    "344","12-09","Wiesława Leokadii Joanny",NULL
    "345","12-10","Julii, Danieli, Bogdana",NULL
    "346","12-11","Damazego, Waldemara, Daniela",NULL
    "347","12-12","Dagmary, Aleksandra, Ady",NULL
    "348","12-13","Lucji, Otylii",NULL
    "349","12-14","Alfreda, Izydora, Jana",NULL
    "350","12-15","Niny, Celiny, Waleriana",NULL
    "351","12-16","Albiny, Zdzisławy, Alicji",NULL
    "352","12-17","Olimpii, Łazarza, Floriana",NULL
    "353","12-18","Gracjana, Bogusława, Laurencji",NULL
    "354","12-19","Gabrieli, Dariusza, Eleonory",NULL
    "355","12-20","Bogumiły, Dominika",NULL
    "356","12-21","Tomisława, Seweryna, Piotra",NULL
    "357","12-22","Zenona, Honoraty, Franciszki",NULL
    "358","12-23","Wiktorii, Sławomiry, Jana",NULL
    "359","12-24","Adama, Ewy, Eweliny",NULL
    "360","12-25","Anastazji, Eugenii",NULL
    "361","12-26","Dionizego, Szczepana",NULL
    "362","12-27","Jana, Żanety, Maksyma",NULL
    "363","12-28","Teofilii, Godzisława, Cezarego",NULL
    "364","12-29","Dawida, Tomasza, Dominika",NULL
    "365","12-30","Rainera, Eugeniusza, Irmy",NULL
    "366","12-31","Sylwestra, Melanii, Mariusza",NULL
  9. Etap 2: Animacja i strona HTML

    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).

  10. 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 jako kalendarz.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
    Podgląd strony po kroku 10
  11. 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/....

    kalendarz.php PHP nowy plik
    <!DOCTYPE html>
    <html>
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  12. Krok 12: Język strony

    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. 1 min
    Polecenie z arkusza

    Zadeklarowany polski język zawartości witryny.

    lang="pl" w <html>.

    kalendarz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  13. Krok 13: Kodowanie polskich znaków

    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. 1 min
    Polecenie z arkusza

    Jawnie zastosowany właściwy standard kodowania polskich znaków.

    <meta charset="UTF-8"> jako pierwszy element <head>.

    kalendarz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  14. Krok 14: Tytuł strony i viewport

    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. 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.

    kalendarz.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  15. Krok 15: Podpięcie arkusza stylów

    Kryteria:

    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).

    kalendarz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  16. 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.

    kalendarz.php PHP zmienione: 12 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
        </header>
        <section id="caption">
        </section>
        <section id="left">
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  17. Krok 17: Nagłówek pierwszego stopnia

    Kryteria:

    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...”.

    <h1> w <header>.

    kalendarz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
        </section>
        <section id="left">
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  18. Krok 18: Blok napisu: akapit na wynik skryptu

    Kryteria:

    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.

    Pusty akapit <p> - treść wstawi Skrypt 1.

    kalendarz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  19. Krok 19: Tabela: część nagłówkowa

    Kryteria:

    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.

    kalendarz.php PHP zmienione: 8 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
            </table>
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  20. 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.

    kalendarz.php PHP zmienione: 24 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  21. Krok 21: Tabela: miesiące po 30 dni i luty

    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. 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).

    kalendarz.php PHP zmienione: 17 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  22. Krok 22: Blok środkowy: nagłówek drugiego stopnia

    Kryteria:

    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.

    kalendarz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  23. 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).

    kalendarz.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
            </form>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  24. Krok 24: Pole daty tylko z 2024 roku, wymagane

    Kryteria:

    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.

    kalendarz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
                <input type="date" name="date" min="2024-01-01" max="2024-12-31" required aria-label="Data imienin">
            </form>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  25. Krok 25: Przycisk „wyślij”

    Kryteria: ,

    R.2.8 W bloku środkowym umieszczony formularz z polem edycyjnym i przyciskiem "wyślij", zastosowany znacznik <form>

    R.3.6 Przycisk realizuje funkcję wysłania danych z formularza (input lub button z typem submit lub button bez typu )

    ok. 1 min
    Polecenie z arkusza

    Przycisk o treści „wyślij” wysyłający dane do skryptu z formularza.

    <button type="submit"> w środku <form> (R.3.6).

    kalendarz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
                <input type="date" name="date" min="2024-01-01" max="2024-12-31" required aria-label="Data imienin">
                <button type="submit">wyślij</button>
            </form>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  26. Krok 26: Animacja jako odnośnik do Wikipedii

    Kryteria: ,

    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.

    kalendarz.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
                <input type="date" name="date" min="2024-01-01" max="2024-12-31" required aria-label="Data imienin">
                <button type="submit">wyślij</button>
            </form>
        </section>
        <section id="right">
            <a href="https://pl.wikipedia.org/wiki/Kalendarz_Majów" target="_blank" rel="noopener">
                <img src="kalendarz.gif" alt="Kalendarz Majów" width="500" height="500">
            </a>
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  27. Krok 27: Nagłówek „Rodzaje kalendarzy”

    Kryteria:

    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”.

    Drugi <h2>, pod obrazem.

    kalendarz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
                <input type="date" name="date" min="2024-01-01" max="2024-12-31" required aria-label="Data imienin">
                <button type="submit">wyślij</button>
            </form>
        </section>
        <section id="right">
            <a href="https://pl.wikipedia.org/wiki/Kalendarz_Majów" target="_blank" rel="noopener">
                <img src="kalendarz.gif" alt="Kalendarz Majów" width="500" height="500">
            </a>
            <h2>Rodzaje kalendarzy</h2>
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  28. 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>.

    kalendarz.php PHP zmienione: 15 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
                <input type="date" name="date" min="2024-01-01" max="2024-12-31" required aria-label="Data imienin">
                <button type="submit">wyślij</button>
            </form>
        </section>
        <section id="right">
            <a href="https://pl.wikipedia.org/wiki/Kalendarz_Majów" target="_blank" rel="noopener">
                <img src="kalendarz.gif" alt="Kalendarz Majów" width="500" height="500">
            </a>
            <h2>Rodzaje kalendarzy</h2>
            <ol>
                <li>słoneczny
                    <ul>
                        <li>kalendarz Majów</li>
                        <li>juliański</li>
                        <li>gregoriański</li>
                    </ul>
                </li>
                <li>księżycowy
                    <ul>
                        <li>starogrecki</li>
                        <li>babiloński</li>
                    </ul>
                </li>
            </ol>
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  29. Krok 29: Stopka

    Kryteria:

    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.

    kalendarz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
                <input type="date" name="date" min="2024-01-01" max="2024-12-31" required aria-label="Data imienin">
                <button type="submit">wyślij</button>
            </form>
        </section>
        <section id="right">
            <a href="https://pl.wikipedia.org/wiki/Kalendarz_Majów" target="_blank" rel="noopener">
                <img src="kalendarz.gif" alt="Kalendarz Majów" width="500" height="500">
            </a>
            <h2>Rodzaje kalendarzy</h2>
            <ol>
                <li>słoneczny
                    <ul>
                        <li>kalendarz Majów</li>
                        <li>juliański</li>
                        <li>gregoriański</li>
                    </ul>
                </li>
                <li>księżycowy
                    <ul>
                        <li>starogrecki</li>
                        <li>babiloński</li>
                    </ul>
                </li>
            </ol>
        </section>
        <footer>
            <p>Stronę opracował(a): Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  30. Etap 3: Styl CSS

    Kroki 30-38 · po tym etapie masz 33 z 43 kryteriów (pkt)

    Krok 30: Zmienne z kolorami i czcionka strony

    Kryteria:

    R.4.1 Ustawiony dla ciała strony (dla body lub kontenera całej strony ): krój czcionki Bookman, Serif (tylko taka kolejność jest prawidłowa )

    ok. 2 min
    Polecenie z arkusza

    Dla ciała strony: krój czcionki Bookman, a w przypadku braku: czcionka Serif.

    Cztery kolory z arkusza w zmiennych w :root. Krój: Bookman, a gdy go nie ma - dowolny szeryfowy serif; klucz uznaje tylko tę kolejność (R.4.1).

    styl.css CSS nowy plik
    :root {
        --color-dark: Indigo;
        --color-violet: BlueViolet;
        --color-lavender: Lavender;
        --color-white: GhostWhite;
    }
    body {
        font-family: Bookman, serif;
    }
    Podgląd strony po tym kroku (kalendarz.php)
  31. Krok 31: Układ: siatka z nazwanymi obszarami

    Kryteria:

    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).

    styl.css CSS zmienione: 27 linii
    :root {
        --color-dark: Indigo;
        --color-violet: BlueViolet;
        --color-lavender: Lavender;
        --color-white: GhostWhite;
    }
    body {
        font-family: Bookman, serif;
    }
    body {
        display: grid;
        grid-template-columns: 25% 40% 35%;
        grid-template-areas:
            "header  header  header"
            "caption caption caption"
            "left    middle  right"
            "footer  footer  footer";
    }
    header {
        grid-area: header;
    }
    #caption {
        grid-area: caption;
    }
    #left {
        grid-area: left;
    }
    #middle {
        grid-area: middle;
    }
    #right {
        grid-area: right;
    }
    footer {
        grid-area: footer;
    }
    Podgląd strony po tym kroku (kalendarz.php)
  32. Krok 32: Nagłówek i stopka

    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

    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.

    Jedna reguła dla dwóch selektorów.

    styl.css CSS zmienione: 6 linii
    :root {
        --color-dark: Indigo;
        --color-violet: BlueViolet;
        --color-lavender: Lavender;
        --color-white: GhostWhite;
    }
    body {
        font-family: Bookman, serif;
    }
    body {
        display: grid;
        grid-template-columns: 25% 40% 35%;
        grid-template-areas:
            "header  header  header"
            "caption caption caption"
            "left    middle  right"
            "footer  footer  footer";
    }
    header {
        grid-area: header;
    }
    #caption {
        grid-area: caption;
    }
    #left {
        grid-area: left;
    }
    #middle {
        grid-area: middle;
    }
    #right {
        grid-area: right;
    }
    footer {
        grid-area: footer;
    }
    header, footer {
        background-color: var(--color-dark);
        color: white;
        padding: 10px;
        text-align: center;
    }
    Podgląd strony po tym kroku (kalendarz.php)
  33. Krok 33: Blok napisu

    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

    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.

    Selektor identyfikatora z #.

    styl.css CSS zmienione: 5 linii
    :root {
        --color-dark: Indigo;
        --color-violet: BlueViolet;
        --color-lavender: Lavender;
        --color-white: GhostWhite;
    }
    body {
        font-family: Bookman, serif;
    }
    body {
        display: grid;
        grid-template-columns: 25% 40% 35%;
        grid-template-areas:
            "header  header  header"
            "caption caption caption"
            "left    middle  right"
            "footer  footer  footer";
    }
    header {
        grid-area: header;
    }
    #caption {
        grid-area: caption;
    }
    #left {
        grid-area: left;
    }
    #middle {
        grid-area: middle;
    }
    #right {
        grid-area: right;
    }
    footer {
        grid-area: footer;
    }
    header, footer {
        background-color: var(--color-dark);
        color: white;
        padding: 10px;
        text-align: center;
    }
    #caption {
        background-color: var(--color-violet);
        padding: 10px;
        text-align: right;
    }
    Podgląd strony po tym kroku (kalendarz.php)
  34. 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.

    styl.css CSS zmienione: 6 linii
    :root {
        --color-dark: Indigo;
        --color-violet: BlueViolet;
        --color-lavender: Lavender;
        --color-white: GhostWhite;
    }
    body {
        font-family: Bookman, serif;
    }
    body {
        display: grid;
        grid-template-columns: 25% 40% 35%;
        grid-template-areas:
            "header  header  header"
            "caption caption caption"
            "left    middle  right"
            "footer  footer  footer";
    }
    header {
        grid-area: header;
    }
    #caption {
        grid-area: caption;
    }
    #left {
        grid-area: left;
    }
    #middle {
        grid-area: middle;
    }
    #right {
        grid-area: right;
    }
    footer {
        grid-area: footer;
    }
    header, footer {
        background-color: var(--color-dark);
        color: white;
        padding: 10px;
        text-align: center;
    }
    #caption {
        background-color: var(--color-violet);
        padding: 10px;
        text-align: right;
    }
    #left, #right {
        background-color: var(--color-lavender);
    }
    #left, #middle, #right {
        height: 500px;
    }
    Podgląd strony po tym kroku (kalendarz.php)
  35. Krok 35: Blok środkowy

    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

    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).

    styl.css CSS zmienione: 4 linie
    :root {
        --color-dark: Indigo;
        --color-violet: BlueViolet;
        --color-lavender: Lavender;
        --color-white: GhostWhite;
    }
    body {
        font-family: Bookman, serif;
    }
    body {
        display: grid;
        grid-template-columns: 25% 40% 35%;
        grid-template-areas:
            "header  header  header"
            "caption caption caption"
            "left    middle  right"
            "footer  footer  footer";
    }
    header {
        grid-area: header;
    }
    #caption {
        grid-area: caption;
    }
    #left {
        grid-area: left;
    }
    #middle {
        grid-area: middle;
    }
    #right {
        grid-area: right;
    }
    footer {
        grid-area: footer;
    }
    header, footer {
        background-color: var(--color-dark);
        color: white;
        padding: 10px;
        text-align: center;
    }
    #caption {
        background-color: var(--color-violet);
        padding: 10px;
        text-align: right;
    }
    #left, #right {
        background-color: var(--color-lavender);
    }
    #left, #middle, #right {
        height: 500px;
    }
    #middle {
        background-color: var(--color-white);
        text-align: center;
    }
    Podgląd strony po tym kroku (kalendarz.php)
  36. Krok 36: Obraz: po prawej, opływany tekstem

    Kryteria: , ,

    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).

    styl.css CSS zmienione: 6 linii
    :root {
        --color-dark: Indigo;
        --color-violet: BlueViolet;
        --color-lavender: Lavender;
        --color-white: GhostWhite;
    }
    body {
        font-family: Bookman, serif;
    }
    body {
        display: grid;
        grid-template-columns: 25% 40% 35%;
        grid-template-areas:
            "header  header  header"
            "caption caption caption"
            "left    middle  right"
            "footer  footer  footer";
    }
    header {
        grid-area: header;
    }
    #caption {
        grid-area: caption;
    }
    #left {
        grid-area: left;
    }
    #middle {
        grid-area: middle;
    }
    #right {
        grid-area: right;
    }
    footer {
        grid-area: footer;
    }
    header, footer {
        background-color: var(--color-dark);
        color: white;
        padding: 10px;
        text-align: center;
    }
    #caption {
        background-color: var(--color-violet);
        padding: 10px;
        text-align: right;
    }
    #left, #right {
        background-color: var(--color-lavender);
    }
    #left, #middle, #right {
        height: 500px;
    }
    #middle {
        background-color: var(--color-white);
        text-align: center;
    }
    img {
        float: right;
        width: 50%;
        height: auto;
        padding: 10px;
    }
    Podgląd strony po tym kroku (kalendarz.php)
  37. Krok 37: Akapity: biała, większa kursywa

    Kryteria:

    R.4.8 Ustawione dla selektora p: rozmiar czcionki 150%, pochylenie, biały kolor

    ok. 1 min
    Polecenie z arkusza

    Dla selektora paragrafu: biały kolor czcionki, rozmiar czcionki 150%, pochylenie czcionki.

    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.

    styl.css CSS zmienione: 5 linii
    :root {
        --color-dark: Indigo;
        --color-violet: BlueViolet;
        --color-lavender: Lavender;
        --color-white: GhostWhite;
    }
    body {
        font-family: Bookman, serif;
    }
    body {
        display: grid;
        grid-template-columns: 25% 40% 35%;
        grid-template-areas:
            "header  header  header"
            "caption caption caption"
            "left    middle  right"
            "footer  footer  footer";
    }
    header {
        grid-area: header;
    }
    #caption {
        grid-area: caption;
    }
    #left {
        grid-area: left;
    }
    #middle {
        grid-area: middle;
    }
    #right {
        grid-area: right;
    }
    footer {
        grid-area: footer;
    }
    header, footer {
        background-color: var(--color-dark);
        color: white;
        padding: 10px;
        text-align: center;
    }
    #caption {
        background-color: var(--color-violet);
        padding: 10px;
        text-align: right;
    }
    #left, #right {
        background-color: var(--color-lavender);
    }
    #left, #middle, #right {
        height: 500px;
    }
    #middle {
        background-color: var(--color-white);
        text-align: center;
    }
    img {
        float: right;
        width: 50%;
        height: auto;
        padding: 10px;
    }
    p {
        color: white;
        font-size: 150%;
        font-style: italic;
    }
    Podgląd strony po tym kroku (kalendarz.php)
  38. Krok 38: Tabela i formularz: marginesy, ramki

    Kryteria: , ,

    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,
    • th, td - odstęp tekstu od ramki (R.4.6).
    styl.css CSS zmienione: 10 linii
    :root {
        --color-dark: Indigo;
        --color-violet: BlueViolet;
        --color-lavender: Lavender;
        --color-white: GhostWhite;
    }
    body {
        font-family: Bookman, serif;
    }
    body {
        display: grid;
        grid-template-columns: 25% 40% 35%;
        grid-template-areas:
            "header  header  header"
            "caption caption caption"
            "left    middle  right"
            "footer  footer  footer";
    }
    header {
        grid-area: header;
    }
    #caption {
        grid-area: caption;
    }
    #left {
        grid-area: left;
    }
    #middle {
        grid-area: middle;
    }
    #right {
        grid-area: right;
    }
    footer {
        grid-area: footer;
    }
    header, footer {
        background-color: var(--color-dark);
        color: white;
        padding: 10px;
        text-align: center;
    }
    #caption {
        background-color: var(--color-violet);
        padding: 10px;
        text-align: right;
    }
    #left, #right {
        background-color: var(--color-lavender);
    }
    #left, #middle, #right {
        height: 500px;
    }
    #middle {
        background-color: var(--color-white);
        text-align: center;
    }
    img {
        float: right;
        width: 50%;
        height: auto;
        padding: 10px;
    }
    p {
        color: white;
        font-size: 150%;
        font-style: italic;
    }
    table, form {
        margin: 30px;
    }
    table, td {
        border: 1px solid var(--color-dark);
        border-collapse: collapse;
    }
    th, td {
        padding: 3px;
    }
    Podgląd strony po tym kroku (kalendarz.php)
  39. Etap 4: Skrypty PHP

    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.

    kalendarz.php PHP zmienione: 12 linii
    <?php
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=kalendarz;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
        $pdo = null;
    } catch (PDOException $exception) {
        error_log($exception->getMessage());
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
                <input type="date" name="date" min="2024-01-01" max="2024-12-31" required aria-label="Data imienin">
                <button type="submit">wyślij</button>
            </form>
        </section>
        <section id="right">
            <a href="https://pl.wikipedia.org/wiki/Kalendarz_Majów" target="_blank" rel="noopener">
                <img src="kalendarz.gif" alt="Kalendarz Majów" width="500" height="500">
            </a>
            <h2>Rodzaje kalendarzy</h2>
            <ol>
                <li>słoneczny
                    <ul>
                        <li>kalendarz Majów</li>
                        <li>juliański</li>
                        <li>gregoriański</li>
                    </ul>
                </li>
                <li>księżycowy
                    <ul>
                        <li>starogrecki</li>
                        <li>babiloński</li>
                    </ul>
                </li>
            </ol>
        </section>
        <footer>
            <p>Stronę opracował(a): Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  40. Krok 40: Skrypt 1: dzień tygodnia po polsku

    Kryteria:

    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.

    kalendarz.php PHP zmienione: 5 linii
    <?php
    const DAYS = ['poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota', 'niedziela'];
    
    // Skrypt 1: dzisiejsza data
    $today = new DateTimeImmutable();
    $dayName = DAYS[(int) $today->format('N') - 1];
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=kalendarz;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
        $pdo = null;
    } catch (PDOException $exception) {
        error_log($exception->getMessage());
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
                <input type="date" name="date" min="2024-01-01" max="2024-12-31" required aria-label="Data imienin">
                <button type="submit">wyślij</button>
            </form>
        </section>
        <section id="right">
            <a href="https://pl.wikipedia.org/wiki/Kalendarz_Majów" target="_blank" rel="noopener">
                <img src="kalendarz.gif" alt="Kalendarz Majów" width="500" height="500">
            </a>
            <h2>Rodzaje kalendarzy</h2>
            <ol>
                <li>słoneczny
                    <ul>
                        <li>kalendarz Majów</li>
                        <li>juliański</li>
                        <li>gregoriański</li>
                    </ul>
                </li>
                <li>księżycowy
                    <ul>
                        <li>starogrecki</li>
                        <li>babiloński</li>
                    </ul>
                </li>
            </ol>
        </section>
        <footer>
            <p>Stronę opracował(a): Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

    Podgląd strony bez zmian - taki jak po kroku 39.

  41. 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.

    kalendarz.php PHP zmienione: 2 linie
    <?php
    const DAYS = ['poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota', 'niedziela'];
    
    // Skrypt 1: dzisiejsza data
    $today = new DateTimeImmutable();
    $dayName = DAYS[(int) $today->format('N') - 1];
    $todayMonthDay = $today->format('m-d');
    $todayFull = $today->format('d-m-Y');
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=kalendarz;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
        $pdo = null;
    } catch (PDOException $exception) {
        error_log($exception->getMessage());
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
                <input type="date" name="date" min="2024-01-01" max="2024-12-31" required aria-label="Data imienin">
                <button type="submit">wyślij</button>
            </form>
        </section>
        <section id="right">
            <a href="https://pl.wikipedia.org/wiki/Kalendarz_Majów" target="_blank" rel="noopener">
                <img src="kalendarz.gif" alt="Kalendarz Majów" width="500" height="500">
            </a>
            <h2>Rodzaje kalendarzy</h2>
            <ol>
                <li>słoneczny
                    <ul>
                        <li>kalendarz Majów</li>
                        <li>juliański</li>
                        <li>gregoriański</li>
                    </ul>
                </li>
                <li>księżycowy
                    <ul>
                        <li>starogrecki</li>
                        <li>babiloński</li>
                    </ul>
                </li>
            </ol>
        </section>
        <footer>
            <p>Stronę opracował(a): Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

    Podgląd strony bez zmian - taki jak po kroku 39.

  42. Krok 42: Funkcja namesForDay: zapytanie 2 przygotowane

    Kryteria:

    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 funkcja namesForDay(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).

    kalendarz.php PHP zmienione: 8 linii
    <?php
    const DAYS = ['poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota', 'niedziela'];
    
    function namesForDay(PDO $pdo, string $monthDay): string
    {
        $statement = $pdo->prepare('SELECT imiona FROM imieniny WHERE data = :day');
        $statement->execute(['day' => $monthDay]);
        return $statement->fetchColumn() ?: 'brak danych';
    }
    
    // Skrypt 1: dzisiejsza data
    $today = new DateTimeImmutable();
    $dayName = DAYS[(int) $today->format('N') - 1];
    $todayMonthDay = $today->format('m-d');
    $todayFull = $today->format('d-m-Y');
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=kalendarz;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
        $todayNames = namesForDay($pdo, $todayMonthDay);
        $pdo = null;
    } catch (PDOException $exception) {
        error_log($exception->getMessage());
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
                <input type="date" name="date" min="2024-01-01" max="2024-12-31" required aria-label="Data imienin">
                <button type="submit">wyślij</button>
            </form>
        </section>
        <section id="right">
            <a href="https://pl.wikipedia.org/wiki/Kalendarz_Majów" target="_blank" rel="noopener">
                <img src="kalendarz.gif" alt="Kalendarz Majów" width="500" height="500">
            </a>
            <h2>Rodzaje kalendarzy</h2>
            <ol>
                <li>słoneczny
                    <ul>
                        <li>kalendarz Majów</li>
                        <li>juliański</li>
                        <li>gregoriański</li>
                    </ul>
                </li>
                <li>księżycowy
                    <ul>
                        <li>starogrecki</li>
                        <li>babiloński</li>
                    </ul>
                </li>
            </ol>
        </section>
        <footer>
            <p>Stronę opracował(a): Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

    Podgląd strony bez zmian - taki jak po kroku 39.

  43. Krok 43: Skrypt 1: zdanie w bloku napisu

    Kryteria: ,

    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).

    kalendarz.php PHP zmienione: 9 linii
    <?php
    const DAYS = ['poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota', 'niedziela'];
    
    function e(string $text): string
    {
        return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
    }
    
    function namesForDay(PDO $pdo, string $monthDay): string
    {
        $statement = $pdo->prepare('SELECT imiona FROM imieniny WHERE data = :day');
        $statement->execute(['day' => $monthDay]);
        return $statement->fetchColumn() ?: 'brak danych';
    }
    
    // Skrypt 1: dzisiejsza data
    $today = new DateTimeImmutable();
    $dayName = DAYS[(int) $today->format('N') - 1];
    $todayMonthDay = $today->format('m-d');
    $todayFull = $today->format('d-m-Y');
    
    $todayText = 'Nie udało się odczytać imienin z bazy.';
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=kalendarz;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
        $todayText = "Dzisiaj jest $dayName, $todayFull, imieniny: " . namesForDay($pdo, $todayMonthDay);
        $pdo = null;
    } catch (PDOException $exception) {
        error_log($exception->getMessage());
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p><?= e($todayText) ?></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
                <input type="date" name="date" min="2024-01-01" max="2024-12-31" required aria-label="Data imienin">
                <button type="submit">wyślij</button>
            </form>
        </section>
        <section id="right">
            <a href="https://pl.wikipedia.org/wiki/Kalendarz_Majów" target="_blank" rel="noopener">
                <img src="kalendarz.gif" alt="Kalendarz Majów" width="500" height="500">
            </a>
            <h2>Rodzaje kalendarzy</h2>
            <ol>
                <li>słoneczny
                    <ul>
                        <li>kalendarz Majów</li>
                        <li>juliański</li>
                        <li>gregoriański</li>
                    </ul>
                </li>
                <li>księżycowy
                    <ul>
                        <li>starogrecki</li>
                        <li>babiloński</li>
                    </ul>
                </li>
            </ol>
        </section>
        <footer>
            <p>Stronę opracował(a): Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  44. Krok 44: Skrypt 2: data z tablicy $_POST

    Kryteria:

    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.

    kalendarz.php PHP zmienione: 3 linie
    <?php
    const DAYS = ['poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota', 'niedziela'];
    
    function e(string $text): string
    {
        return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
    }
    
    function namesForDay(PDO $pdo, string $monthDay): string
    {
        $statement = $pdo->prepare('SELECT imiona FROM imieniny WHERE data = :day');
        $statement->execute(['day' => $monthDay]);
        return $statement->fetchColumn() ?: 'brak danych';
    }
    
    // Skrypt 1: dzisiejsza data
    $today = new DateTimeImmutable();
    $dayName = DAYS[(int) $today->format('N') - 1];
    $todayMonthDay = $today->format('m-d');
    $todayFull = $today->format('d-m-Y');
    
    // Skrypt 2: data z formularza
    $dateText = $_POST['date'] ?? null;
    
    $todayText = 'Nie udało się odczytać imienin z bazy.';
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=kalendarz;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
        $todayText = "Dzisiaj jest $dayName, $todayFull, imieniny: " . namesForDay($pdo, $todayMonthDay);
        $pdo = null;
    } catch (PDOException $exception) {
        error_log($exception->getMessage());
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p><?= e($todayText) ?></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
                <input type="date" name="date" min="2024-01-01" max="2024-12-31" required aria-label="Data imienin">
                <button type="submit">wyślij</button>
            </form>
        </section>
        <section id="right">
            <a href="https://pl.wikipedia.org/wiki/Kalendarz_Majów" target="_blank" rel="noopener">
                <img src="kalendarz.gif" alt="Kalendarz Majów" width="500" height="500">
            </a>
            <h2>Rodzaje kalendarzy</h2>
            <ol>
                <li>słoneczny
                    <ul>
                        <li>kalendarz Majów</li>
                        <li>juliański</li>
                        <li>gregoriański</li>
                    </ul>
                </li>
                <li>księżycowy
                    <ul>
                        <li>starogrecki</li>
                        <li>babiloński</li>
                    </ul>
                </li>
            </ol>
        </section>
        <footer>
            <p>Stronę opracował(a): Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

    Podgląd strony bez zmian - taki jak po kroku 43.

  45. 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.

    kalendarz.php PHP zmienione: 9 linii
    <?php
    const DAYS = ['poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota', 'niedziela'];
    
    function e(string $text): string
    {
        return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
    }
    
    function namesForDay(PDO $pdo, string $monthDay): string
    {
        $statement = $pdo->prepare('SELECT imiona FROM imieniny WHERE data = :day');
        $statement->execute(['day' => $monthDay]);
        return $statement->fetchColumn() ?: 'brak danych';
    }
    
    // Skrypt 1: dzisiejsza data
    $today = new DateTimeImmutable();
    $dayName = DAYS[(int) $today->format('N') - 1];
    $todayMonthDay = $today->format('m-d');
    $todayFull = $today->format('d-m-Y');
    
    // Skrypt 2: data z formularza
    $dateText = $_POST['date'] ?? null;
    $selectedDate = null;
    $dateError = '';
    if (is_string($dateText)) {
        $selectedDate = DateTimeImmutable::createFromFormat('!Y-m-d', $dateText);
        if (!$selectedDate || $selectedDate->format('Y-m-d') !== $dateText || $selectedDate->format('Y') !== '2024') {
            $selectedDate = null;
            $dateError = 'Podaj poprawną datę z 2024 roku.';
        }
    }
    
    $todayText = 'Nie udało się odczytać imienin z bazy.';
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=kalendarz;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
        $todayText = "Dzisiaj jest $dayName, $todayFull, imieniny: " . namesForDay($pdo, $todayMonthDay);
        $pdo = null;
    } catch (PDOException $exception) {
        error_log($exception->getMessage());
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p><?= e($todayText) ?></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
                <input type="date" name="date" min="2024-01-01" max="2024-12-31" required aria-label="Data imienin">
                <button type="submit">wyślij</button>
            </form>
        </section>
        <section id="right">
            <a href="https://pl.wikipedia.org/wiki/Kalendarz_Majów" target="_blank" rel="noopener">
                <img src="kalendarz.gif" alt="Kalendarz Majów" width="500" height="500">
            </a>
            <h2>Rodzaje kalendarzy</h2>
            <ol>
                <li>słoneczny
                    <ul>
                        <li>kalendarz Majów</li>
                        <li>juliański</li>
                        <li>gregoriański</li>
                    </ul>
                </li>
                <li>księżycowy
                    <ul>
                        <li>starogrecki</li>
                        <li>babiloński</li>
                    </ul>
                </li>
            </ol>
        </section>
        <footer>
            <p>Stronę opracował(a): Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>

    Podgląd strony bez zmian - taki jak po kroku 43.

  46. Krok 46: Skrypt 2: imieniny pod formularzem

    Kryteria: , ,

    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).

    kalendarz.php PHP zmienione: 10 linii
    <?php
    const DAYS = ['poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota', 'niedziela'];
    
    function e(string $text): string
    {
        return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
    }
    
    function namesForDay(PDO $pdo, string $monthDay): string
    {
        $statement = $pdo->prepare('SELECT imiona FROM imieniny WHERE data = :day');
        $statement->execute(['day' => $monthDay]);
        return $statement->fetchColumn() ?: 'brak danych';
    }
    
    // Skrypt 1: dzisiejsza data
    $today = new DateTimeImmutable();
    $dayName = DAYS[(int) $today->format('N') - 1];
    $todayMonthDay = $today->format('m-d');
    $todayFull = $today->format('d-m-Y');
    
    // Skrypt 2: data z formularza
    $dateText = $_POST['date'] ?? null;
    $selectedDate = null;
    $dateError = '';
    if (is_string($dateText)) {
        $selectedDate = DateTimeImmutable::createFromFormat('!Y-m-d', $dateText);
        if (!$selectedDate || $selectedDate->format('Y-m-d') !== $dateText || $selectedDate->format('Y') !== '2024') {
            $selectedDate = null;
            $dateError = 'Podaj poprawną datę z 2024 roku.';
        }
    }
    
    $todayText = 'Nie udało się odczytać imienin z bazy.';
    $selectedNames = null;
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=kalendarz;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
        $todayText = "Dzisiaj jest $dayName, $todayFull, imieniny: " . namesForDay($pdo, $todayMonthDay);
        if ($selectedDate !== null) {
            $selectedNames = namesForDay($pdo, $selectedDate->format('m-d'));
        }
        $pdo = null;
    } catch (PDOException $exception) {
        error_log($exception->getMessage());
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Kalendarz</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Dni, miesiące, lata...</h1>
        </header>
        <section id="caption">
            <p><?= e($todayText) ?></p>
        </section>
        <section id="left">
            <table>
                <thead>
                    <tr>
                        <th scope="col">liczba dni</th>
                        <th scope="col">miesiąc</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td rowspan="7">31</td>
                        <td>styczeń</td>
                    </tr>
                    <tr>
                        <td>marzec</td>
                    </tr>
                    <tr>
                        <td>maj</td>
                    </tr>
                    <tr>
                        <td>lipiec</td>
                    </tr>
                    <tr>
                        <td>sierpień</td>
                    </tr>
                    <tr>
                        <td>październik</td>
                    </tr>
                    <tr>
                        <td>grudzień</td>
                    </tr>
                    <tr>
                        <td rowspan="4">30</td>
                        <td>kwiecień</td>
                    </tr>
                    <tr>
                        <td>czerwiec</td>
                    </tr>
                    <tr>
                        <td>wrzesień</td>
                    </tr>
                    <tr>
                        <td>listopad</td>
                    </tr>
                    <tr>
                        <td>28 lub 29</td>
                        <td>luty</td>
                    </tr>
                </tbody>
            </table>
        </section>
        <section id="middle">
            <h2>Sprawdź kto ma urodziny</h2>
            <form method="post">
                <input type="date" name="date" min="2024-01-01" max="2024-12-31" required aria-label="Data imienin" value="<?= e($selectedDate ? $dateText : '') ?>">
                <button type="submit">wyślij</button>
            </form>
            <?php if ($selectedNames !== null): ?>
                <div>Dnia <?= e($dateText) ?> są imieniny: <?= e($selectedNames) ?></div>
            <?php elseif ($dateError !== ''): ?>
                <div><?= e($dateError) ?></div>
            <?php endif; ?>
        </section>
        <section id="right">
            <a href="https://pl.wikipedia.org/wiki/Kalendarz_Majów" target="_blank" rel="noopener">
                <img src="kalendarz.gif" alt="Kalendarz Majów" width="500" height="500">
            </a>
            <h2>Rodzaje kalendarzy</h2>
            <ol>
                <li>słoneczny
                    <ul>
                        <li>kalendarz Majów</li>
                        <li>juliański</li>
                        <li>gregoriański</li>
                    </ul>
                </li>
                <li>księżycowy
                    <ul>
                        <li>starogrecki</li>
                        <li>babiloński</li>
                    </ul>
                </li>
            </ol>
        </section>
        <footer>
            <p>Stronę opracował(a): Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kalendarz.php)
  47. Etap 5: Porównanie z wersją podstawową

    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 podstawowata wersja
    układfloat: left i clear: bothgrid-template-areas, szerokości w grid-template-columns
    kolorywpisane w regułachzmienne w :root
    bazamysqli_* z tabeli 1PDO, wyjątki, połączenie zamknięte przed HTML-em
    zapytaniedata wklejona w napis zapytania, dwa razyjedna funkcja z zapytaniem przygotowanym
    datadate(), strtotimeDateTimeImmutable, createFromFormat
    2024-02-31imieniny z 2 marca„Podaj poprawną datę z 2024 roku.”
    awaria bazybłąd PHP w połowie stronykomunikat w bloku napisu, szczegóły w dzienniku
    wypisywanieecho danych wproste() 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.

    Podgląd strony bez zmian - taki jak po kroku 46.

  48. Krok 48: Którą wersję wybrać na egzaminie

    ok. 2 min
    Polecenie z arkusza

    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ę.

    Podgląd strony bez zmian - taki jak po kroku 46.

  49. Etap 6: Oddanie pracy

    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.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

    Podgląd strony bez zmian - taki jak po kroku 46.

Podgląd

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: . 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.