Serwis używa plików cookies do analizy ruchu i poprawy działania. Szczegóły
EE.09-01-22.01-SGStyczeń 2022 · 44 kroki · ok. 81 min · 31 kryteriów z klucza
Rozwiązanie krok po kroku: Zgłoszenie na kartę wędkarską (Nowoczesny kod (flex, PDO))
To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza wedkowanie z czterema zapytaniami, zdjęcie wędki o wysokości 220 px, strona karta.html z formularzem zgłoszenia i skrypt zapisz.php zapisujący dane w bazie - i tak samo spełnia każde kryterium klucza. Inna jest droga:
semantyczne znaczniki: baner w <header>, blok główny w <main>, trzy dolne bloki w <section>,
flexbox zamiast float: dolne bloki stoją w kontenerze display: flex, a szerokości 20%, 40% i 40% zostają na blokach - tak, jak ocenia je klucz,
zmienne CSS dla kolorów z arkusza, etykiety <label for>, przyciski <button>, pola z required i autocomplete,
PHP na PDO z zapytaniem przygotowanym, sprawdzeniem metody żądania i pustych pól, obsługą błędów w try / catch i zamknięciem połączenia w finally,
strona z potwierdzeniem zamiast pustej strony po zapisie, z danymi przepuszczonymi przez htmlspecialchars, oraz przekierowanie po zapisie - odświeżenie nie doda drugiej karty.
To arkusz EE.09 ze stycznia 2022 - kwalifikacji formuły 2017, którą zastąpiła INF.03. Baza i zdjęcie pochodzą z oryginalnego archiwum CKE pliki1.zip (załącznik na stronie arkusza), zapytania i zrzuty są policzone na MariaDB 10.4, a podgląd od kroków z PHP to wynik prawdziwego uruchomienia kodu w PHP 8.2 (klucz każe sprawdzać w XAMPP 8.0.7 - użyte konstrukcje działają w obu wersjach).
Jak liczą się punkty. Klucz ma 31 kryteriów (R.1.1 - R.5.4), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 24 punkty. Przy każdym kroku jest napisane, które kryteria spełnia; klucz przyjmuje zarówno mysqli, jak i PDO.
Suwak i strzałki obok niego - albo ←→ na klawiaturze - przechodzą krok po kroku; wyjaśnienie, pliki i podgląd zmieniają się razem z krokiem.
Lista „Etap” przenosi od razu do wybranego etapu.
„Rozwiązuję samodzielnie” chowa rozwiązanie kroku - najpierw własna próba, potem odsłonięcie.
„Tryb prezentacji” pokazuje same kroki, bez menu strony - na rzutnik.
Etap 1: Baza danych
Kroki 1-7 · po tym etapie masz 6 z 31 kryteriów (pkt)
Krok 1: Folder zdającego i archiwum pliki1.zip
ok. 2 min
Polecenie z arkusza
Należy utworzyć folder o nazwie odpowiadającej numerowi PESEL zdającego lub w przypadku jego braku innemu numerowi, którym został podpisany arkusz. Archiwum należy rozpakować do tego folderu.
Folder na pulpicie nazwany numerem PESEL (w tym rozwiązaniu w jego miejscu stoi Bartosz Bryniarski), do niego archiwum pliki1.zip rozpakowane z hasłem K@RTY*. W środku: baza.sql i wedka.jpg. Do tego folderu trafiają wszystkie rezultaty pracy.
Krok 2: XAMPP i baza wedkowanie
ok. 2 min
Polecenie z arkusza
Uruchom usługi MySQL i Apache za pomocą XAMPP Control Panel. Za pomocą narzędzia phpMyAdmin wykonaj podane operacje na bazie danych: Utwórz bazę danych o nazwie wedkowanie
Start przy Apache i MySQL, potem http://localhost/phpmyadmin, Nowa, nazwa wedkowanie, porównywanie np. utf8mb4_polish_ci.
Krok 3: Import pliku baza.sql i zrzut import.png
Kryteria:
R.1.1 Wykonano import tabel do bazy danych wedkowanie , czynność udokumentowano plikiem o nazwie import w formacie PNG. Zrzut zawiera cały obszar ekranu z widocznym paskiem zadań
ok. 3 min
Polecenie z arkusza
Do bazy wedkowanie zaimportuj tabele z pliku baza.sql z rozpakowanego archiwum. Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w folderze z numerem PESEL, lub w przypadku jego braku w folderze z innym numerem, którym został podpisany arkusz, w formacie PNG i nazwij import. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel
Baza wedkowanie, karta Import, plik baza.sql, Wykonaj. Po komunikacie „Import zakończył się sukcesem” w lewym panelu jest 11 tabel; zadanie używa trzech: karty_wedkarskie, lowisko i zawody_wedkarskie. Zrzut całego ekranu z paskiem zadań: import.png.
Typowe błędy
Ten zrzut zapisz jako PNG, zrzuty zapytań (kw1 - kw4) - jako JPEG.
Podgląd strony po tym kroku
Krok 4: Zapytanie 1: karta Grzegorza Niemczyka
Kryteria: ,
R.1.2 Zapisano plik tekstowy o nazwie kwerendy zawierający co najmniej jedno zapytanie SQL, wynikające z treści zadania
R.1.3 Utworzono zapytanie 1 dodające rekord do tabeli karty_wedkarskie dla Grzegorza Niemczyka, adres="Gdynia, Batorego 14/5", z datą "2018-02-23", punkty=0. Baza powinna sama nadać wartość pola id dla tabeli. W pliku z kwerendami lub na zrzucie istnieje zapis np.: INSERT INTO `karty_wedkarskie` VALUES (NULL, 'Grzegorz', 'Niemczyk', 'Gdynia, Batorego 14/5', '2018-02-23', '0'); oraz wynik działania udokumentowano zrzutem, na którym widoczne jest poprawnie wykonane zapytanie lub tabela z dodanym rekordem
ok. 3 min
Polecenie z arkusza
Zapytanie 1: dodające rekord do tabeli Karty_wedkarskie dla Grzegorza Niemczyka, zamieszkałego pod adresem „Gdynia, Batorego 14/5”, z datą „2018-02-23”; wartość punktów: 0. Baza powinna sama nadać wartość pola id dla tabeli
Wartości dla wszystkich sześciu kolumn w kolejności z tabeli. NULL w kolumnie id z AUTO_INCREMENT - numer nada baza (Grzegorz dostaje 3). Data w formacie RRRR-MM-DD, punkty jako liczba. Zapytanie trafia do kwerendy.txt (R.1.2), zrzut z dodanym rekordem - do kw1.jpg. To samo zapytanie, z parametrami w miejscu danych, wykona później skrypt.
Krok 5: Zapytanie 2: wędkarze z liczbą punktów większą niż 20
Kryteria:
R.1.4 Utworzono zapytanie 2 wybierające jedynie pola imie i nazwisko z tabeli karty_wedkarskie dla wędkarzy, dla których liczba punktów jest większa niż 20. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, nazwisko FROM `karty_wedkarskie` WHERE punkty > 20; oraz wynik działania udokumentowano zrzutem, na którym widoczny jest dokładnie 1 rekord: Jan Kowalski; jedynie pola imie, nazwisko
ok. 2 min
Polecenie z arkusza
Zapytanie 2: wybierające jedynie pola imie i nazwisko z tabeli Karty_wedkarskie dla wędkarzy, dla których liczba punktów jest większa niż 20
Dwie kolumny, warunek punkty > 20 (ostro większa). Wynik: jeden wędkarz, Jan Kowalski. Zrzut: kw2.jpg. Każda klauzula w osobnej linii - przy dłuższych zapytaniach łatwiej wtedy znaleźć błąd.
Krok 6: Zapytanie 3: akwen, gdzie sędzią jest Krzysztof Dobrowolski
Kryteria:
R.1.5 Utworzono zapytanie 3 wybierające jedynie pole akwen z tabeli lowisko dla łowisk, gdzie sędzią zawodów jest Krzysztof Dobrowolski. Zapytanie wykorzystuje relację. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT akwen FROM lowisko JOIN zawody_wedkarskie ON lowisko.id = zawody_wedkarskie.Lowisko_id WHERE sedzia= "Krzysztof Dobrowolski"; możliwe INNER JOIN lub SELECT akwen FROM lowisko, zawody_wedkarskie WHERE lowisko.id = zawody_wedkarskie.Lowisko_id AND sedzia= "Krzysztof Dobrowolski"; oraz wynik działania udokumentowano zrzutem, na którym widoczny jest dokładnie 1 rekord: Zalew Wegrowski; jedynie pole akwen
ok. 3 min
Polecenie z arkusza
Zapytanie 3: wybierające jedynie pole akwen z tabeli Lowisko dla łowisk, gdzie sędzią zawodów jest Krzysztof Dobrowolski, należy użyć relacji
Relacja łączy zawody z łowiskiem przez kolumnę Lowisko_id: JOIN zawody_wedkarskie ON lowisko.id = zawody_wedkarskie.Lowisko_id, a WHERE zostawia zawody jednego sędziego. Wynik: Zalew Wegrowski. Zrzut: kw3.jpg.
R.1.6 Utworzono zapytanie 4 tworzące użytkownika anna na localhost z hasłem anna123. W pliku z kwerendami lub na zrzucie istnieje zapis np.: CREATE USER "anna"@"localhost" IDENTIFIED BY "anna123"; oraz wynik działania udokumentowano zrzutem wskazującym na prawidłowo dodanego użytkownika
ok. 2 min
Polecenie z arkusza
Zapytanie 4: tworzące użytkownika anna na localhost z hasłem anna123
Nazwa i host w osobnych apostrofach: 'anna'@'localhost', hasło po IDENTIFIED BY. Żeby zrzut kw4.jpg pokazywał nowe konto, pod zapytaniem 4 w tej samej karcie SQL dopisz SELECT User, Host, Password FROM mysql.user WHERE User = 'anna'; - do kwerendy.txt trafia tylko zapytanie 4.
Typowe błędy
anna123 to hasło do ćwiczeń - na prawdziwym serwerze konto dostaje długie losowe hasło.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1INSERT INTO karty_wedkarskie VALUES (NULL, 'Grzegorz', 'Niemczyk', 'Gdynia, Batorego 14/5', '2018-02-23', 0);-- Zapytanie 2SELECT imie, nazwiskoFROM karty_wedkarskieWHERE punkty > 20;-- Zapytanie 3SELECT akwenFROM lowiskoJOIN zawody_wedkarskie ON lowisko.id = zawody_wedkarskie.Lowisko_idWHERE sedzia = 'Krzysztof Dobrowolski';-- Zapytanie 4CREATE USER 'anna'@'localhost' IDENTIFIED BY 'anna123';
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 8-26 · po tym etapie masz 18 z 31 kryteriów (pkt)
Krok 8: Grafika: wysokość 220 px z zachowaniem proporcji
Kryteria:
R.2.1 Plik wedka.jpg przeskalowano z zachowaniem proporcji tak, że jego wysokość wynosi dokładnie 220 px, odpowiadająca temu szerokość wynosi 330 px ±5 px
ok. 2 min
Polecenie z arkusza
Plik wedka.jpg, wypakowany z archiwum, należy przeskalować z zachowaniem proporcji tak, aby jego wysokość wynosiła dokładnie 220 px
GIMP, Obraz → Skaluj obraz, łańcuch zamknięty, wysokość 220 px - szerokość przelicza się na 330 px (500 × 220 / 333). Plik → Nadpisz wedka.jpg.
Podgląd strony po tym kroku
Krok 9: Plik karta.html
ok. 1 min
Polecenie z arkusza
Składa się ze strony o nazwie karta.html oraz skryptu zapisz.php. Poniższe wymagania dotyczą tylko pliku karta.html
Szkielet HTML5 w pliku karta.html. <meta name="viewport"> każe telefonom wyświetlić stronę w naturalnej szerokości ekranu, zamiast pomniejszać widok komputerowy.
R.3.5 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl_1.css , formatowanie pochodzi jedynie z tego arkusza Uwaga: kryterium to nie jest spełnione również, gdy źle przypisano co najmniej jeden selektor do bloku (np. kropka zamiast #)
ok. 1 min
Polecenie z arkusza
Arkusz stylów w pliku o nazwie styl_1.css prawidłowo połączony z kodem strony
<link rel="stylesheet" href="styl_1.css"> - nazwa z podkreśleniem i cyfrą (R.3.5).
R.2.4 Wygląd strony zdefiniowano dzieląc ją na bloki: baner, główny, trzy bloki: lewy, środkowy i prawy. Zastosowano znaczniki sekcji
ok. 2 min
Polecenie z arkusza
Podział strony na bloki: na górze blok banera, poniżej blok główny, na dole trzy bloki: lewy, środkowy i prawy. Podział zrealizowany za pomocą znaczników sekcji tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z Obrazem 2
Każdy blok dostaje znacznik, który mówi, czym jest:
<header> - baner strony,
<main> - główna treść, czyli formularz; na stronie jest jeden <main>, więc nie potrzebuje identyfikatora,
trzy <section> z klasami left, middle i right - dolne bloki.
Dolne sekcje stoją we wspólnym kontenerze <div class="bottom">. div nie ma znaczenia dla treści - służy wyłącznie do ułożenia trzech bloków obok siebie (R.2.4).
Krok 16: Formularz wysyłający dane metodą POST do zapisz.php
Kryteria:
R.3.4 Formularz wysyła dane metodą POST do pliku zapisz.php
ok. 2 min
Polecenie z arkusza
Formularz wysyłający dane metodą POST do pliku zapisz.php zawierający pola
action="zapisz.php" - dokąd, method="post" - jak: dane jadą w treści żądania i trafią do $_POST (R.3.4). Stronę otwierasz przez http://localhost/…, żeby serwer wykonał skrypt.
Napis to <label for="first-name">, a pole ma ten sam id="first-name" - etykieta jest powiązana z polem: kliknięcie napisu ustawia kursor w polu, a czytnik ekranu odczytuje go jako nazwę pola. Napis stanie nad polem dzięki regule CSS dla wiersza .row - bez <br> w HTML-u.
name="imie" - klucz w $_POST, taki jak nazwa kolumny,
required - przeglądarka nie wyśle formularza z pustym polem,
Pole edycyjne podpisane powyżej tekstem: „adres: ”; pole ma rozmiar 30
size="30" - szerokość pola na około 30 znaków, dokładnie to, co mówi arkusz. Klucz przyjmuje też szerokość w CSS, ale atrybut jest najprostszy i widać go od razu w kodzie (R.2.8).
Przycisk czyszczący zawartość formularza z etykietą „CZYŚĆ”
<button type="reset"> - napis stoi między znacznikami, więc można w nim umieścić także ikonę albo pogrubienie. Typ trzeba podać jawnie: <button> bez type w formularzu domyślnie wysyła dane.
R.2.8 W bloku głównym umieszczono formularz z trzema polami edycyjnymi w tym pole do wpisania adresu ma rozmiar 30 (size lub maxlength lub width lub w CSS) oraz dwoma przyciskami "CZYŚĆ" i "ZAPISZ"
R.3.3 Pierwszy przycisk czyści zawartość formularza, drugi przycisk wysyła dane z formularza (input z typem submit lub button)
ok. 1 min
Polecenie z arkusza
Przycisk wysyłający zawartość formularza z etykietą „ZAPISZ”
<button type="submit"> - drugi przycisk wysyła formularz. Klucz wprost przyjmuje button (R.3.3). Formularz ma komplet: trzy pola, pole adresu o rozmiarze 30 i dwa przyciski (R.2.8).
R.2.6 W bloku lewym umieszczono listę punktowaną (nieuporządkowaną) z czterema elementami: Zalewy, Stawy, Jeziora, Rzeki, zastosowano znaczniki <ul>, <li> oraz ich zamknięcia
ok. 1 min
Polecenie z arkusza
Lista punktowana (nieuporządkowana) zawierająca elementy: Zalewy, Stawy, Jeziora, Rzeki
Krok 24: Blok środkowy: zdjęcie z tekstem alternatywnym
Kryteria:
R.2.7 W bloku środkowym umieszczono obraz wedka.jpg oraz ma on tekst alternatywny "karta wędkarska"
ok. 1 min
Polecenie z arkusza
Zawartość bloku środkowego: obraz wedka.jpg z tekstem alternatywnym o treści: „karta wędkarska”
<img> z alt="karta wędkarska" (R.2.7). Atrybuty width i height z wymiarami pliku po skalowaniu rezerwują miejsce na zdjęcie, zanim się wczyta - strona nie „skacze” przy ładowaniu.
R.2.5 W banerze zapisano nagłówek h2: "Zgłoszenie na kartę wędkarską" oraz zapisano przynajmniej jeden nagłówek h4 z: "Formularz - karta wędkarska" w bloku głównym lub "Typy łowisk" w lewym oraz w bloku prawym paragraf z numerem PESEL lub innym numerem, którym został podpisany arkusz
ok. 1 min
Polecenie z arkusza
Zawartość bloku prawego: Akapit (paragraf) o treści: „Stronę przygotował: ”, dalej wstawiony numer PESEL zdającego lub w przypadku jego braku inny numer, którym został podpisany arkusz
Na egzaminie po dwukropku wpisujesz PESEL; tu w jego miejscu stoi Bartosz Bryniarski. Z nagłówkami <h2> i <h4> daje to R.2.5.
Kroki 27-35 · po tym etapie masz 27 z 31 kryteriów (pkt)
Krok 27: Plik styl_1.css i zmienne z kolorami arkusza
ok. 2 min
Polecenie z arkusza
Cechy formatowania CSS: Są zawarte wyłącznie w zewnętrznym arkuszu stylów
Nowy plik styl_1.css. Na początku zmienne CSS w :root: kolor DodgerBlue powtarza się w czterech blokach, a wysokość 220 px w trzech. Każdą wartość wpisujesz raz, a reguły odwołują się do niej przez var(--blue) - zmiana koloru to zmiana jednej linii. Wartości to nazwy z arkusza, więc egzaminator znajdzie je w pliku.
Etykieta i pole są elementami w linii - bez stylu stanęłyby obok siebie. Wiersz .row jako kolumna flex (flex-direction: column) układa je jeden pod drugim, jak na obrazie 2, a align-items: flex-start zostawia polom ich naturalną szerokość z size (bez tej linii rozciągnęłyby się na całą szerokość bloku). Arkusz nie podaje stylu formularza, a obraz 2 pokazuje pola pod napisami - ta reguła tylko to odtwarza.
R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z Obrazem 2 w arkuszu egzaminacyjnym (prawidłowo zastosowano właściwości CSS układające bloki na stronie, np. float i clear albo display flex albo grid)
ok. 2 min
Polecenie z arkusza
Podział zrealizowany za pomocą znaczników sekcji tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z Obrazem 2
display: flex na kontenerze .bottom ustawia jego dzieci - trzy sekcje - w jednym rzędzie, bez float i bez clear (R.3.1). Szerokości dostaną same bloki w kolejnych krokach: arkusz z 2022 roku i jego klucz oceniają szerokość bloków (20% i 40%), więc tam zostaje width, a kontener tylko je układa.
R.4.2 Ustawiono kolor tła DodgerBlue dla banera i trzech bloków dolnych oraz kolor LightBlue dla bloku głównego
R.4.3 Ustawiono biały kolor czcionki dla banera i trzech bloków dolnych
R.4.4 Ustawiono wysokość trzech bloków dolnych na 220px
R.4.5 Ustawiono szerokość dolnych bloków: lewego na 20% oraz środkowego i prawego na 40%
R.4.6 Ustawiono wyrównanie tekstu do środka dla banera, bloku środkowego i prawego
ok. 2 min
Polecenie z arkusza
Wspólne dla bloku środkowego i bloku prawego: kolor tła DodgerBlue, biały kolor czcionki, szerokość 40%, wysokość 220 px, wyrównanie tekstu do środka
Dwa selektory po przecinku, jedna reguła. Komplet: kolory tła (R.4.2), biały tekst (R.4.3), wysokości (R.4.4), szerokości 20 + 40 + 40 = 100% (R.4.5) i wyśrodkowanie banera, bloku środkowego i prawego (R.4.6). Flex nie zawija bloków do nowego wiersza, więc nawet zaokrąglenia pikseli nie zepchną bloku prawego pod pozostałe.
Krok 35: Odnośnik: obramowanie kreskowane, tło i kolor tekstu
Kryteria:
R.4.8 Ustawiono styl odnośnika: obramowanie 1px dashed DimGray, kolor tła Gold, kolor czcionki DarkRed, marginesy wewnętrzne 10px (selektor a lub klasa lub identyfikator)
ok. 1 min
Polecenie z arkusza
Dla znacznika odnośnika: obramowanie linią kreskowaną o szerokości 1 px i kolorze DimGray, kolor tła Gold, kolor czcionki DarkRed, marginesy wewnętrzne 10 px
border: 1px dashed DimGray - szerokość, linia kreskowana, kolor (R.4.8). Te kolory występują w pliku raz, więc zostają wpisane wprost.
Kroki 36-42 · po tym etapie masz 31 z 31 kryteriów (pkt)
Krok 36: Plik zapisz.php, metoda żądania i połączenie PDO z bazą
Kryteria:
R.5.1 Skrypt realizuje połączenie z serwerem bazy danych i wybór bazy wedkowanie
ok. 3 min
Polecenie z arkusza
Skrypt połączenia z bazą. Napisany w języku PHP, w pliku zapisz.php. Skrypt łączy się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie wedkowanie
Plik zapisz.php zaczyna się od sprawdzenia, jak go otwarto:
$_SERVER['REQUEST_METHOD'] !== 'POST' - ktoś wszedł na adres skryptu wprost (z historii, z zakładki, robot). Wtedy header('Location: karta.html') odsyła go do formularza, a exit kończy skrypt - sam nagłówek go nie zatrzymuje. Sprawdzone: takie wejście dostaje odpowiedź 302 i nic nie trafia do bazy,
new PDO(...) - adres serwera localhost, baza wedkowanie i kodowanie w jednym napisie, potem użytkownik root i puste hasło (R.5.1). ERRMODE_EXCEPTION - każdy błąd bazy rzuca wyjątek, który obsłuży jeden blok catch.
PDO zamiast funkcji mysqli z tabeli 1 - klucz ocenia połączenie, a nie bibliotekę. Podgląd do kroku z zapytaniem pokazuje formularz.
R.5.4 Skrypt wysyła do bazy danych zapytanie 1 wstawiające dane do bazy: pola data_zezwolenia i punkty = NULL, pozostałe wartości wypełnione są danymi z formularza. Należy sprawdzić w bazie czy rekord został dodany
ok. 3 min
Polecenie z arkusza
Skrypt wysyła do bazy danych zmodyfikowane zapytanie 1, które w polach data_zezwolenia i punkty zawiera wartość NULL, pozostałe wartości wypełnione są danymi z formularza
Zapytanie 1, w którym dane z formularza zastępują parametry:imie, :nazwisko, :adres, a datę i punkty - NULL:
$pdo->prepare(...) - baza dostaje samą treść zapytania,
$statement->execute([...]) - osobno przychodzą wartości parametrów.
Dane nigdy nie staną się kodem SQL: nazwisko O'Brien zapisuje się bez błędu, a wpisany w pole fragment zapytania zostaje zwykłym tekstem jednego rekordu. Sprawdzenie, jak każe klucz (R.5.4): formularz z danymi Marek, Lis, „Sopot, Morska 3” i w tabeli nowy wiersz 3 z NULL w kolumnach data_zezwolenia i punkty.
Typowe błędy
Tabela z archiwum ma kodowanie latin1 - litery ą, ć, ę, ł, ń, ś, ź, ż zapisują się jako „?” także przez PDO z charset=utf8mb4. Klucz sprawdza import pliku bez zmian, więc kodowania tabeli nie zmieniasz.
Krok 39: Obsługa błędów i zamknięcie połączenia w finally
Kryteria:
R.5.2 Ostatnią operacją na bazie jest jej zamknięcie (zgodne ze składnią)
ok. 3 min
Polecenie z arkusza
Na końcu działania skrypt zamyka połączenie z serwerem.
Połączenie i zapis trafiają do bloku try:
catch (PDOException $exception) - gdy baza nie działa albo zapytanie się nie powiedzie, skrypt ustawia zwykłe zdanie dla użytkownika zamiast komunikatu PHP z danymi serwera,
finally wykonuje się zawsze - po udanym zapisie i po wyjątku. Stoją w nim $statement = null i $pdo = null: PDO nie ma funkcji close, połączenie zamyka się, gdy znika ostatnie odwołanie do obiektu. Zamknięcie jest więc ostatnią operacją na bazie w każdej gałęzi (R.5.2).
Zmienna $message z komunikatem dla użytkownika - udany zapis albo błąd - wyświetli się na stronie w następnym kroku.
Dodatek spoza arkusza - klucz go nie ocenia. Wersja podstawowa po zapisie pokazuje pustą stronę i użytkownik nie wie, czy coś się stało. Tu pod skryptem stoi krótka strona w tym samym wyglądzie (te same header, main i styl_1.css) z komunikatem i odnośnikiem z powrotem do formularza.
Komunikat zawiera imię i nazwisko wpisane przez użytkownika, więc przed wypisaniem przechodzi przez e() - krótką funkcję z htmlspecialchars. Sprawdzone: imię <b>Ola</b> wyświetla się dosłownie jako tekst ze znacznikami, a nie jako pogrubienie - tak samo nie wykona się wpisany w pole <script>. Gdy baza nie odpowiada (sprawdzone na złym haśle), strona pokazuje zdanie z catch, bez nazwy serwera i treści błędu. Podgląd: strona po zapisaniu karty Marka Lisa.
Pola mają required, ale to zabezpieczenie przeglądarki - dane da się wysłać z pominięciem formularza (np. poleceniem curl albo po usunięciu atrybutu w narzędziach przeglądarki). Dlatego skrypt sprawdza je jeszcze raz: gdy po trim() któreś pole jest puste, zamiast zapisu ustawia komunikat „Wypełnij wszystkie pola formularza.” i w ogóle nie łączy się z bazą. Porównanie === '' zamiast empty() - empty('0') jest prawdziwe, więc adres „0” uznano by za puste pole.
Sprawdzone: nazwisko z samych spacji nie dodaje rekordu. Podgląd: ten przypadek.
Krok 42: Odświeżenie po zapisie nie dodaje drugiej karty
ok. 4 min
Strona z potwierdzeniem jest wynikiem żądania POST, więc odświeżenie (F5) pyta, czy wysłać dane ponownie - a ponowne wysłanie dopisałoby drugą identyczną kartę. Wzorzec PRG (Post/Redirect/Get):
session_start() na początku pliku - sesja przechowa komunikat między dwoma żądaniami,
po udanym zapisie ($saved = true ustawiane zaraz po execute) i po bloku finally komunikat trafia do $_SESSION, a header('Location: zapisz.php') z exit każe przeglądarce otworzyć skrypt jeszcze raz zwykłym żądaniem GET,
żądanie GET z komunikatem w sesji wyświetla go i od razu usuwa (unset); GET bez komunikatu - jak wcześniej - wraca do formularza.
Sprawdzone na prawdziwym PHP: wysłanie formularza daje odpowiedź 302, potem stronę z potwierdzeniem, a kolejne odświeżenie - powrót do formularza, bez drugiego rekordu w tabeli. Błąd (puste pole) nie przekierowuje - komunikat zostaje na stronie. Podgląd: stan po przekierowaniu.
zapisz.phpPHPzmienione: 41 linii
<?phpsession_start();functione(string $text): string{returnhtmlspecialchars($text, ENT_QUOTES, 'UTF-8');}if ($_SERVER['REQUEST_METHOD'] !== 'POST') {// po przekierowaniu: komunikat zapisany w sesji wyświetla się jeden razif (!isset($_SESSION['message'])) {header('Location: karta.html');exit; }$message = $_SESSION['message'];unset($_SESSION['message']);} else {$firstName = trim($_POST['imie'] ?? '');$lastName = trim($_POST['nazwisko'] ?? '');$address = trim($_POST['adres'] ?? '');if ($firstName === '' || $lastName === '' || $address === '') {$message = 'Wypełnij wszystkie pola formularza.'; } else {$saved = false;$message = 'Zapisano zgłoszenie na kartę wędkarską: ' . $firstName . ' ' . $lastName . '.';try {$pdo = new PDO('mysql:host=localhost;dbname=wedkowanie;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, ]);$statement = $pdo->prepare('INSERT INTO karty_wedkarskie VALUES (NULL, :imie, :nazwisko, :adres, NULL, NULL);');$statement->execute(['imie' => $firstName,'nazwisko' => $lastName,'adres' => $address, ]);$saved = true; } catch (PDOException $exception) {$message = 'Nie udało się zapisać zgłoszenia, spróbuj ponownie za chwilę.'; } finally {$statement = null;$pdo = null; }if ($saved) {// PRG: komunikat do sesji i przekierowanie - odświeżenie strony nie zapisze karty drugi raz$_SESSION['message'] = $message;header('Location: zapisz.php');exit; } }}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Karty wędkarskie</title> <linkrel="stylesheet"href="styl_1.css"></head><body> <header> <h2>Zgłoszenie na kartę wędkarską</h2> </header> <main> <h4>Formularz - karta wędkarska</h4> <p><?= e($message) ?></p> <ahref="karta.html">Wróć do formularza</a> </main></body></html>
Podgląd strony po tym kroku (zapisz.php)
Etap 5: Porównanie z wersją podstawową
Krok 43 · po tym etapie masz 31 z 31 kryteriów (pkt)
Krok 43: Co jest inaczej i którą wersję wybrać na egzaminie
ok. 3 min
Obie wersje dają komplet 31 punktów. Różnice:
wersja podstawowa
wersja nowoczesna
bloki
header i cztery section z id
header, main, trzy section z klasami
dolny rząd
float: left na blokach
kontener display: flex, width na blokach
kolory
wpisane w każdej regule
zmienne --blue, --light-blue
formularz
napis, <br>, pole, input type="reset"
label for, wiersze w div, button, required, autocomplete
biblioteka
mysqli (tabela 1 arkusza)
PDO z wyjątkami
wejście bez formularza
ostrzeżenia PHP i pusty rekord
przekierowanie do formularza
INSERT
dane wklejone w treść zapytania
parametry :imie, :nazwisko, :adres
puste pola
zapisują się
komunikat, bez połączenia z bazą
zamknięcie bazy
mysqli_close na końcu
$pdo = null w finally
po zapisie
pusta strona, F5 dodaje drugą kartę
potwierdzenie, przekierowanie
Na egzaminie wersja podstawowa trzyma się funkcji z tabeli 1 i łatwiej ją napisać bez dokumentacji. Nowoczesna nie wywraca się na apostrofie, nie zapisuje pustych kart i nie dubluje ich po odświeżeniu - a klucz przyjmuje obie. Na prawdziwym serwerze skrypt nie łączyłby się kontem root bez hasła, tylko kontem z prawem INSERT do jednej tabeli, a dane logowania leżałyby w osobnym pliku poza katalogiem strony.
Krok 44 · po tym etapie masz 31 z 31 kryteriów (pkt)
Krok 44: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
UWAGA: po zakończeniu pracy utwórz w folderze z numerem PESEL lub w przypadku jego braku w folderze z innym numerem, którym został podpisany arkusz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowano poprawność działania witryny. Nagraj płytę z rezultatami pracy.
W przeglądarka.txt nazwa przeglądarki, w której sprawdzana była strona. W folderze z numerem zdającego: import.png, karta.html, kw1.jpg - kw4.jpg, kwerendy.txt, przeglądarka.txt, styl_1.css, wedka.jpg i zapisz.php. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem zdającego.
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
To jedno z możliwych rozwiązań. Egzaminator ocenia spełnienie kryteriów z klucza odpowiedzi, a nie zgodność z tym kodem - inna, poprawna droga też daje punkty.
Autor rozwiązania: Bartosz Bryniarski. Licencja CC BY-NC 4.0 - kopiowanie i przeróbki do celów niekomercyjnych, z podaniem autora i źródła (link do tej strony) (zasady wykorzystania). Treść arkusza i klucza oceniania pochodzi z CKE.