Serwis używa plików cookies do analizy ruchu i poprawy działania. Szczegóły
EE.09-03-22.01-SGStyczeń 2022 · 47 kroków · ok. 88 min · 34 kryteria z klucza
Rozwiązanie krok po kroku: Dodawanie zespołu pogotowia ratunkowego (Nowoczesny kod (flex, PDO))
To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza ee09 z czterema zapytaniami, zdjęcie karetki o wysokości 100 px, strona ratownicy.html z formularzem dodania zespołu i skrypt dodanie.php, który zapisuje zespół i wypisuje wysłane zapytanie - i tak samo spełnia każde kryterium klucza. Inna jest droga:
semantyczne znaczniki: baner w <header>, blok główny w <main>, stopka w <footer> - w banerze i stopce po trzy <section>,
flexbox zamiast float: <header> i <footer> są kontenerami display: flex, a szerokości 55%, 25% i 20% zostają na blokach - tak, jak ocenia je klucz,
zmienne CSS dla kolorów i wysokości z arkusza, etykiety <label for>, przyciski <button>, pola z required,
PHP na PDO z zapytaniem przygotowanym, sprawdzeniem numeru karetki i pustych pól, obsługą błędów w try / catch i zamknięciem połączenia w finally,
wypisane zapytanie złożone tak samo, jak składa je PDO, i porównane z dziennikiem serwera bazy - na ekranie jest dokładnie to, co dostała baza, przepuszczone przez htmlspecialchars,
strona z komunikatem w wyglądzie formularza oraz przekierowanie po zapisie - odświeżenie nie doda drugiego zespołu.
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 pliki3.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 34 kryteria (R.1.1 - R.5.5), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 26 punktów. 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 34 kryteriów (pkt)
Krok 1: Folder zdającego i archiwum pliki3.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 pliki3.zip rozpakowane z hasłem ##Pogotowi3$. W środku: baza3.sql i obraz.jpg. Do tego folderu trafiają wszystkie rezultaty pracy.
Krok 2: XAMPP i baza ee09
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 ee09
Start przy Apache i MySQL, potem http://localhost/phpmyadmin, Nowa, nazwa ee09, porównywanie np. utf8mb4_polish_ci.
Krok 3: Import pliku baza3.sql i zrzut import.png
Kryteria:
R.1.1 Wykonano import tabel do bazy danych ee09 , czynność udokumentowano plikiem o nazwie import w formacie PNG
ok. 3 min
Polecenie z arkusza
Do bazy ee09 zaimportuj tabele z pliku baza3.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 ee09, karta Import, plik baza3.sql, Wykonaj. Po komunikacie „Import zakończył się sukcesem” w lewym panelu jest 12 tabel; zadanie używa trzech: ratownicy, dyspozytorzy i zgloszenia. 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: nowy zespół karetki 20
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 ratownicy o kolejnych wartościach pól : NULL, 20, Adam Nowak, Jan Kowalski, Anna Nowakowska. Możliwe również zamiast NULL pominięcie pola id. W pliku z kwerendami lub na zrzucie istnieje zapis np.: INSERT INTO ratownicy VALUES (NULL, 20, 'Adam Nowak', 'Jan Kowalski', 'Anna Nowakowska'); oraz wynik działania zapytania udokumentowano zrzutem, na którym jest widoczne poprawne wykonane zapytanie lub tabela z dodanymi danymi
ok. 3 min
Polecenie z arkusza
Zapytanie 1: dodające rekord do tabeli ratownicy o wartościach: nrKaretki - 20, ratownicy, kolejno - Adam Nowak, Jan Kowalski, Anna Nowakowska. Baza powinna sama nadać wartość pola id dla tabeli
Wartości dla wszystkich pięciu kolumn w kolejności z tabeli. NULL w kolumnie id z AUTO_INCREMENT - numer nada baza (nowy zespół dostaje 5). Numer karetki jako liczba, imiona i nazwiska w apostrofach. 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: zgłoszenia dyspozytora o id 4
Kryteria:
R.1.4 Utworzono zapytanie 2 wybierające jedynie pola id, adres oraz ratownicy_id z tabeli zgloszenia, dla pola dyspozytorzy_id = 4. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id, adres, ratownicy_id FROM zgloszenia WHERE dyspozytorzy_id = 4; oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczne są jedynie pola id, adres i ratownicy_id dla dokładnie 3 rekordów o id = 1, 2, 6
ok. 2 min
Polecenie z arkusza
Zapytanie 2: wybierające jedynie pola id, adres oraz ratownicy_id z tabeli zgloszenia, dla zgłoszeń przyjętych przez dyspozytora o id 4
Trzy kolumny, warunek na kluczu obcym dyspozytorzy_id = 4 (nie na id zgłoszenia). Wynik: zgłoszenia 1, 2 i 6. Zrzut: kw2.jpg. Każda klauzula w osobnej linii - przy dłuższych zapytaniach łatwiej wtedy znaleźć błąd.
R.1.5 Utworzono zapytanie 3 tworzące użytkownika adam z hasłem Adam6& W pliku z kwerendami lub na zrzucie istnieje zapis np.: CREATE USER 'adam' IDENTIFIED BY 'Adam6&'; (możliwe też z @'localhost') oraz wynik działania zapytania udokumentowano zrzutem wskazującym na dodanie tego użytkownika z hasłem
ok. 2 min
Polecenie z arkusza
Zapytanie 3: tworzące użytkownika adam z hasłem Adam6&
CREATE USER 'adam' IDENTIFIED BY 'Adam6&' - bez podanego hosta konto dostaje host % (klucz przyjmuje też 'adam'@'localhost'). Żeby zrzut kw3.jpg pokazywał konto z hasłem, pod zapytaniem w tej samej karcie SQL dopisz SELECT User, Host, Password FROM mysql.user WHERE User = 'adam'; - do kwerendy.txt trafia tylko zapytanie 3.
Typowe błędy
Adam6& to hasło do ćwiczeń - na prawdziwym serwerze konto dostaje długie losowe hasło i host localhost.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1INSERT INTO ratownicy VALUES (NULL, 20, 'Adam Nowak', 'Jan Kowalski', 'Anna Nowakowska');-- Zapytanie 2SELECT id, adres, ratownicy_idFROM zgloszeniaWHERE dyspozytorzy_id = 4;-- Zapytanie 3CREATE USER 'adam' IDENTIFIED BY 'Adam6&';
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: prawa CREATE, ALTER i DROP do tabeli ratownicy
Kryteria:
R.1.6 Utworzono zapytanie 4 nadające dla użytkownika adam zestaw praw CREATE, ALTER, DROP albo zestaw praw INSERT, UPDATE, DELETE dla tabeli ratownicy . W pliku z kwerendami lub na zrzucie istnieje zapis np.: GRANT CREATE, ALTER, DROP ON ratownicy TO 'adam'; lub GRANT INSERT, UPDATE, DELETE ON ratownicy TO 'adam'; oraz wynik działania zapytania udokumentowano zrzutem wskazującym dodanie zestawu praw na tabeli ratownicy dla użytkownika adam
ok. 2 min
Polecenie z arkusza
Zapytanie 4: nadające dla użytkownika adam prawa tworzenia obiektu, edycji struktury obiektu i usuwania obiektu dla tabeli ratownicy
Tworzenie obiektu to CREATE, edycja struktury - ALTER, usuwanie - DROP; ON ratownicy przy zaznaczonej bazie ee09 oznacza tabelę ee09.ratownicy. Zrzut kw4.jpg z wynikiem SHOW GRANTS FOR 'adam'; dopisanym pod zapytaniem. Klucz przyjmuje też zestaw INSERT, UPDATE, DELETE.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1INSERT INTO ratownicy VALUES (NULL, 20, 'Adam Nowak', 'Jan Kowalski', 'Anna Nowakowska');-- Zapytanie 2SELECT id, adres, ratownicy_idFROM zgloszeniaWHERE dyspozytorzy_id = 4;-- Zapytanie 3CREATE USER 'adam' IDENTIFIED BY 'Adam6&';-- Zapytanie 4GRANT CREATE, ALTER, DROP ON ratownicy TO 'adam';
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 8-26 · po tym etapie masz 18 z 34 kryteriów (pkt)
Krok 8: Zdjęcie karetki: wysokość 100 px
Kryteria:
R.2.1 Plik obraz.jpg przeskalowano z zachowaniem proporcji tak, że jego wysokość wynosi dokładnie 100 px, odpowiadająca temu szerokość wynosi 167 px ±5 px
ok. 2 min
Polecenie z arkusza
Plik obraz.jpg, wypakowany z archiwum, należy przeskalować z zachowaniem proporcji tak, aby jego wysokość wynosiła dokładnie 100 px
GIMP, Obraz → Skaluj obraz, łańcuch zamknięty, wysokość 100 px - szerokość przelicza się na 167 px (566 × 100 / 339). Plik → Nadpisz obraz.jpg.
Podgląd strony po tym kroku
Krok 9: Plik ratownicy.html
ok. 1 min
Polecenie z arkusza
Składa się ze strony o nazwie ratownicy.html oraz skryptu dodanie.php. Poniższe wymagania dotyczą tylko pliku ratownicy.html
Szkielet HTML5 w pliku ratownicy.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 styl3.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 styl3.css prawidłowo połączony z kodem strony
Krok 13: Bloki: header i footer z trzema sekcjami, main
Kryteria:
R.2.4 Wygląd strony zdefiniowano dzieląc ją na bloki: trzy bloki banera, blok główny, trzy bloki stopki. Zastosowano znaczniki sekcji
ok. 2 min
Polecenie z arkusza
Podział strony na bloki: na górze trzy bloki banera: lewy, środkowy, prawy, poniżej blok główny, na dole trzy bloki stopki: lewy, środkowy, 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żda grupa bloków dostaje znacznik, który mówi, czym jest:
<header> - baner strony; w środku trzy bloki banera,
<main> - główna treść, czyli formularz; na stronie jest jeden <main>, więc nie potrzebuje identyfikatora,
<footer> - stopka z trzema blokami.
Bloki to <section> z klasami left, middle i right. Te same klasy w banerze i w stopce, bo arkusz daje lewym, środkowym i prawym blokom obu rzędów te same szerokości - jedna reguła CSS obsłuży dwa bloki (R.2.4). <header> i <footer> posłużą też jako kontenery, które ułożą bloki w rzędzie.
Krok 16: Prawy blok banera: zdjęcie z tekstem alternatywnym
Kryteria:
R.2.7 W prawym bloku banera umieszczono obraz.jpg wraz z tekstem alternatywnym "Ratownicy"
ok. 1 min
Polecenie z arkusza
Zawartość prawego bloku banera: obraz.jpg z tekstem alternatywnym o treści: „Ratownicy”
<img> z alt="Ratownicy" (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.
Krok 18: Formularz wysyłający dane metodą POST do dodanie.php
Kryteria:
R.3.4 Formularz wysyła dane metodą POST do pliku dodanie.php
ok. 2 min
Polecenie z arkusza
Formularz wysyłający dane metodą POST do pliku dodanie.php zawierający pola
action="dodanie.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.
Krok 19: Pole „Numer karetki:” typu number z etykietą
ok. 2 min
Polecenie z arkusza
Pole edycyjne typu numerycznego podpisane powyżej tekstem: „Numer karetki:”
Napis to <label for="ambulance">, a pole ma ten sam id - kliknięcie napisu ustawia kursor w polu, a czytnik ekranu odczytuje napis jako nazwę pola. Nad polem ustawi go reguła CSS dla wiersza .row, bez <br>.
type="number" - pole na liczbę, ze strzałkami (R.3.3 wymaga tego typu w pierwszym polu),
name="nrKaretki" - klucz w $_POST, taki jak nazwa kolumny,
min="1" i required - przeglądarka nie wyśle pustego pola ani numeru 0 czy ujemnego. Skrypt i tak sprawdzi to jeszcze raz.
Krok 20: Trzy pola na imiona i nazwiska ratowników
ok. 2 min
Polecenie z arkusza
Trzy pola edycyjne podpisane powyżej tekstem, kolejno: „Imię i nazwisko pierwszego ratownika:”, „Imię i nazwisko drugiego ratownika:”, „Imię i nazwisko trzeciego ratownika:”
Trzy takie same wiersze: etykieta z for, pole tekstowe z pasującym id i name równym nazwie kolumny (ratownik1 - ratownik3), required. Identyfikatory po angielsku, np. rescuer1, a nazwy pól - jak w bazie.
ratownicy.htmlHTMLzmienione: 12 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <sectionclass="left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionclass="middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionclass="right"> <imgsrc="obraz.jpg"alt="Ratownicy"width="167"height="100"> </section> </header> <main> <h3>Dodaj nowy zespół</h3> <formaction="dodanie.php"method="post"> <divclass="row"> <labelfor="ambulance">Numer karetki:</label> <inputtype="number"id="ambulance"name="nrKaretki"min="1"required> </div> <divclass="row"> <labelfor="rescuer1">Imię i nazwisko pierwszego ratownika:</label> <inputtype="text"id="rescuer1"name="ratownik1"required> </div> <divclass="row"> <labelfor="rescuer2">Imię i nazwisko drugiego ratownika:</label> <inputtype="text"id="rescuer2"name="ratownik2"required> </div> <divclass="row"> <labelfor="rescuer3">Imię i nazwisko trzeciego ratownika:</label> <inputtype="text"id="rescuer3"name="ratownik3"required> </div> </form> </main> <footer> <sectionclass="left"> </section> <sectionclass="middle"> </section> <sectionclass="right"> </section> </footer></body></html>
Podgląd strony po tym kroku (ratownicy.html)
Krok 21: Przycisk „CZYŚĆ”
ok. 1 min
Polecenie z arkusza
Przycisk czyszczący zawartość formularza z etykietą „CZYŚĆ”
<button type="reset"> - napis stoi między znacznikami. Typ trzeba podać jawnie: <button> bez type w formularzu domyślnie wysyła dane.
ratownicy.htmlHTMLzmienione: 3 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <sectionclass="left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionclass="middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionclass="right"> <imgsrc="obraz.jpg"alt="Ratownicy"width="167"height="100"> </section> </header> <main> <h3>Dodaj nowy zespół</h3> <formaction="dodanie.php"method="post"> <divclass="row"> <labelfor="ambulance">Numer karetki:</label> <inputtype="number"id="ambulance"name="nrKaretki"min="1"required> </div> <divclass="row"> <labelfor="rescuer1">Imię i nazwisko pierwszego ratownika:</label> <inputtype="text"id="rescuer1"name="ratownik1"required> </div> <divclass="row"> <labelfor="rescuer2">Imię i nazwisko drugiego ratownika:</label> <inputtype="text"id="rescuer2"name="ratownik2"required> </div> <divclass="row"> <labelfor="rescuer3">Imię i nazwisko trzeciego ratownika:</label> <inputtype="text"id="rescuer3"name="ratownik3"required> </div> <divclass="buttons"> <buttontype="reset">CZYŚĆ</button> </div> </form> </main> <footer> <sectionclass="left"> </section> <sectionclass="middle"> </section> <sectionclass="right"> </section> </footer></body></html>
Podgląd strony po tym kroku (ratownicy.html)
Krok 22: Przycisk „DODAJ”
Kryteria: ,
R.2.8 W bloku głównym umieszczono formularz z czterema polami edycyjnymi oraz dwoma przyciskami "CZYŚĆ" i "DODAJ"
R.3.3 Pierwsze pole formularza jest typu number oraz 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ą „DODAJ”
<button type="submit"> - drugi przycisk wysyła formularz. Klucz wprost przyjmuje button (R.3.3). Formularz ma komplet: cztery pola i dwa przyciski (R.2.8).
ratownicy.htmlHTMLzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <sectionclass="left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionclass="middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionclass="right"> <imgsrc="obraz.jpg"alt="Ratownicy"width="167"height="100"> </section> </header> <main> <h3>Dodaj nowy zespół</h3> <formaction="dodanie.php"method="post"> <divclass="row"> <labelfor="ambulance">Numer karetki:</label> <inputtype="number"id="ambulance"name="nrKaretki"min="1"required> </div> <divclass="row"> <labelfor="rescuer1">Imię i nazwisko pierwszego ratownika:</label> <inputtype="text"id="rescuer1"name="ratownik1"required> </div> <divclass="row"> <labelfor="rescuer2">Imię i nazwisko drugiego ratownika:</label> <inputtype="text"id="rescuer2"name="ratownik2"required> </div> <divclass="row"> <labelfor="rescuer3">Imię i nazwisko trzeciego ratownika:</label> <inputtype="text"id="rescuer3"name="ratownik3"required> </div> <divclass="buttons"> <buttontype="reset">CZYŚĆ</button> <buttontype="submit">DODAJ</button> </div> </form> </main> <footer> <sectionclass="left"> </section> <sectionclass="middle"> </section> <sectionclass="right"> </section> </footer></body></html>
Podgląd strony po tym kroku (ratownicy.html)
Krok 23: Lewy blok stopki: odnośnik do kwerendy.txt
Kryteria:
R.3.2 Po wybraniu odnośnika "Zobacz kwerendy" otwiera się lub pobiera plik kwerendy
ok. 1 min
Polecenie z arkusza
Zawartość lewego bloku stopki: odnośnik o treści „Zobacz kwerendy”, jego kliknięcie otwiera lub pobiera plik kwerendy.txt
Ścieżka względna do pliku w tym samym folderze (R.3.2).
ratownicy.htmlHTMLzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <sectionclass="left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionclass="middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionclass="right"> <imgsrc="obraz.jpg"alt="Ratownicy"width="167"height="100"> </section> </header> <main> <h3>Dodaj nowy zespół</h3> <formaction="dodanie.php"method="post"> <divclass="row"> <labelfor="ambulance">Numer karetki:</label> <inputtype="number"id="ambulance"name="nrKaretki"min="1"required> </div> <divclass="row"> <labelfor="rescuer1">Imię i nazwisko pierwszego ratownika:</label> <inputtype="text"id="rescuer1"name="ratownik1"required> </div> <divclass="row"> <labelfor="rescuer2">Imię i nazwisko drugiego ratownika:</label> <inputtype="text"id="rescuer2"name="ratownik2"required> </div> <divclass="row"> <labelfor="rescuer3">Imię i nazwisko trzeciego ratownika:</label> <inputtype="text"id="rescuer3"name="ratownik3"required> </div> <divclass="buttons"> <buttontype="reset">CZYŚĆ</button> <buttontype="submit">DODAJ</button> </div> </form> </main> <footer> <sectionclass="left"> <ahref="kwerendy.txt">Zobacz kwerendy</a> </section> <sectionclass="middle"> </section> <sectionclass="right"> </section> </footer></body></html>
Podgląd strony po tym kroku (ratownicy.html)
Krok 24: Środkowy blok stopki: nagłówek piątego stopnia
Kryteria:
R.2.5 W lewym bloku banera zapisano nagłówek h2: "Dodanie zespołu ratowniczego" oraz w bloku głównym zapisano nagłówek h3: "Dodaj nowy zespół" oraz w środkowym bloku stopki nagłówek h5: "Przypominamy numery alarmowe" oraz zapisano przynajmniej jeden paragraf
ok. 1 min
Polecenie z arkusza
Zawartość środkowego bloku stopki: Nagłówek piątego stopnia o treści: „Przypominamy numery alarmowe”
<h5> w środkowej sekcji <footer>. Z nagłówkami <h2>, <h3> i paragrafem w banerze daje to R.2.5.
ratownicy.htmlHTMLzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <sectionclass="left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionclass="middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionclass="right"> <imgsrc="obraz.jpg"alt="Ratownicy"width="167"height="100"> </section> </header> <main> <h3>Dodaj nowy zespół</h3> <formaction="dodanie.php"method="post"> <divclass="row"> <labelfor="ambulance">Numer karetki:</label> <inputtype="number"id="ambulance"name="nrKaretki"min="1"required> </div> <divclass="row"> <labelfor="rescuer1">Imię i nazwisko pierwszego ratownika:</label> <inputtype="text"id="rescuer1"name="ratownik1"required> </div> <divclass="row"> <labelfor="rescuer2">Imię i nazwisko drugiego ratownika:</label> <inputtype="text"id="rescuer2"name="ratownik2"required> </div> <divclass="row"> <labelfor="rescuer3">Imię i nazwisko trzeciego ratownika:</label> <inputtype="text"id="rescuer3"name="ratownik3"required> </div> <divclass="buttons"> <buttontype="reset">CZYŚĆ</button> <buttontype="submit">DODAJ</button> </div> </form> </main> <footer> <sectionclass="left"> <ahref="kwerendy.txt">Zobacz kwerendy</a> </section> <sectionclass="middle"> <h5>Przypominamy numery alarmowe</h5> </section> <sectionclass="right"> </section> </footer></body></html>
Podgląd strony po tym kroku (ratownicy.html)
Krok 25: Lista numerowana numerów alarmowych
Kryteria:
R.2.6 W środkowym bloku stopki umieszczono listę numerowaną z dwoma elementami, zastosowano znaczniki <ol>, <li> oraz ich zamknięcia
<ol> z dwoma <li> (R.2.6). Litery zamiast cyfr ustawi CSS.
ratownicy.htmlHTMLzmienione: 4 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <sectionclass="left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionclass="middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionclass="right"> <imgsrc="obraz.jpg"alt="Ratownicy"width="167"height="100"> </section> </header> <main> <h3>Dodaj nowy zespół</h3> <formaction="dodanie.php"method="post"> <divclass="row"> <labelfor="ambulance">Numer karetki:</label> <inputtype="number"id="ambulance"name="nrKaretki"min="1"required> </div> <divclass="row"> <labelfor="rescuer1">Imię i nazwisko pierwszego ratownika:</label> <inputtype="text"id="rescuer1"name="ratownik1"required> </div> <divclass="row"> <labelfor="rescuer2">Imię i nazwisko drugiego ratownika:</label> <inputtype="text"id="rescuer2"name="ratownik2"required> </div> <divclass="row"> <labelfor="rescuer3">Imię i nazwisko trzeciego ratownika:</label> <inputtype="text"id="rescuer3"name="ratownik3"required> </div> <divclass="buttons"> <buttontype="reset">CZYŚĆ</button> <buttontype="submit">DODAJ</button> </div> </form> </main> <footer> <sectionclass="left"> <ahref="kwerendy.txt">Zobacz kwerendy</a> </section> <sectionclass="middle"> <h5>Przypominamy numery alarmowe</h5> <ol> <li>112</li> <li>999</li> </ol> </section> <sectionclass="right"> </section> </footer></body></html>
Podgląd strony po tym kroku (ratownicy.html)
Krok 26: Prawy blok stopki: autor strony
ok. 1 min
Polecenie z arkusza
Zawartość prawego bloku stopki: akapit (paragraf) o treści: „Autor”, łamanie linii, dalej wstawiony numer PESEL zdającego lub w przypadku jego braku inny numer, którym został podpisany arkusz
Na egzaminie po <br> wpisujesz PESEL; tu w jego miejscu stoi Bartosz Bryniarski. Strona HTML jest gotowa.
ratownicy.htmlHTMLzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <sectionclass="left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionclass="middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionclass="right"> <imgsrc="obraz.jpg"alt="Ratownicy"width="167"height="100"> </section> </header> <main> <h3>Dodaj nowy zespół</h3> <formaction="dodanie.php"method="post"> <divclass="row"> <labelfor="ambulance">Numer karetki:</label> <inputtype="number"id="ambulance"name="nrKaretki"min="1"required> </div> <divclass="row"> <labelfor="rescuer1">Imię i nazwisko pierwszego ratownika:</label> <inputtype="text"id="rescuer1"name="ratownik1"required> </div> <divclass="row"> <labelfor="rescuer2">Imię i nazwisko drugiego ratownika:</label> <inputtype="text"id="rescuer2"name="ratownik2"required> </div> <divclass="row"> <labelfor="rescuer3">Imię i nazwisko trzeciego ratownika:</label> <inputtype="text"id="rescuer3"name="ratownik3"required> </div> <divclass="buttons"> <buttontype="reset">CZYŚĆ</button> <buttontype="submit">DODAJ</button> </div> </form> </main> <footer> <sectionclass="left"> <ahref="kwerendy.txt">Zobacz kwerendy</a> </section> <sectionclass="middle"> <h5>Przypominamy numery alarmowe</h5> <ol> <li>112</li> <li>999</li> </ol> </section> <sectionclass="right"> <p>Autor<br>Bartosz Bryniarski</p> </section> </footer></body></html>
Podgląd strony po tym kroku (ratownicy.html)
Etap 3: Styl CSS
Kroki 27-37 · po tym etapie masz 29 z 34 kryteriów (pkt)
Krok 27: Plik styl3.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 styl3.css. Na początku zmienne CSS w :root: kolor SaddleBrown powtarza się w tle bloków, w ramce i w kolorze odnośnika, a Snow - w tle bloku głównego i odnośnika. Każdą wartość wpisujesz raz, a reguły odwołują się do niej przez var(--brown) - zmiana koloru to zmiana jednej linii. Wartości to nazwy z arkusza, więc egzaminator znajdzie je w pliku.
R.4.3 Ustawiono biały kolor czcionki dla wszystkich bloków banera i stopki
R.4.4 Ustawiono wysokość dla wszystkich bloków banera i stopki na 100px
ok. 2 min
Polecenie z arkusza
Wspólne dla wszystkich bloków banera i stopki: kolor tła SaddleBrown, biały kolor czcionki, wysokość 100 px
Selektory potomka header section i footer section trafiają w sześć bloków naraz - bez wyliczania identyfikatorów. Biały tekst (R.4.3) i wysokość 100 px (R.4.4) we wszystkich blokach banera i stopki.
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 <header> i <footer> ustawia ich dzieci - po trzy sekcje - w jednym rzędzie, bez float i bez clear (R.3.1). <main> stoi między nimi jako zwykły blok na całą szerokość. Szerokości dostaną same bloki w kolejnych krokach: arkusz z 2022 roku i jego klucz oceniają szerokość bloków (55%, 25%, 20%), więc tam zostaje width, a kontenery tylko je układają. Flex nie zawija bloków do nowego wiersza, więc nawet zaokrąglenia pikseli nie zepchną prawego bloku niżej.
Krok 31: Lewe bloki: szerokość 55% i większa czcionka
Kryteria:
R.4.8 Ustawiono rozmiar czcionki 120% dla lewych bloków banera i stopki
ok. 1 min
Polecenie z arkusza
Dodatkowo dla lewego bloku banera i lewego bloku stopki: szerokość 55%, rozmiar czcionki 120%
Klasa .left jest na lewym bloku banera i lewym bloku stopki - jedna reguła dla obu (R.4.8). width: 55% liczy się od szerokości kontenera, czyli od szerokości strony.
Krok 35: Odnośnik: kropkowana ramka, tło i wysokość linii
Kryteria:
R.4.9 Ustawiono styl odnośnika: obramowanie 2px dotted SaddleBrown, kolor tła Snow, kolor czcionki SaddleBrown, padding: 20px, wysokość linii 100px (dla selektora a lub indentyfikatora lub klasy)
ok. 1 min
Polecenie z arkusza
Dla odnośnika: obramowanie linią kropkowaną o szerokości 2 px i kolorze SaddleBrown, kolor tła Snow, kolor czcionki SaddleBrown, marginesy wewnętrzne 20 px, wysokość linii 100 px
border: 2px dotted z kolorem ze zmiennej, tło i tekst w odwróconych kolorach bloku, padding: 20px i line-height: 100px - tyle co wysokość stopki (R.4.9).
Pole edycyjne typu numerycznego podpisane powyżej tekstem: „Numer karetki:”
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 naturalną szerokość (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.
Kroki 38-45 · po tym etapie masz 34 z 34 kryteriów (pkt)
Krok 38: Plik dodanie.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 ee09
ok. 3 min
Polecenie z arkusza
Napisany w języku PHP, w pliku dodanie.php. Skrypt łączy się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie ee09
Plik dodanie.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: ratownicy.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 ee09 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 przyjmuje obie biblioteki. Podgląd do kroku z zapytaniem pokazuje formularz.
R.5.3 Skrypt pobiera dane z formularza za pomocą tablicy $_POST (lub za pomocą $_REQUEST gdy sprawdzono, że REQUEST_METHOD jest równe POST)
ok. 2 min
Polecenie z arkusza
Skrypt działa na danych przesłanych z formularza
Cztery wartości z $_POST (R.5.3), od razu sprawdzone i oczyszczone:
filter_var(..., FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) - numer karetki zamienia się na liczbę całkowitą tylko wtedy, gdy naprawdę nią jest i jest większy od zera. Dla pustego pola, tekstu, 2.5 czy -3 wynikiem jest false,
?? '' - gdy pola w ogóle nie wysłano, zmienna dostaje pusty napis zamiast ostrzeżenia „Undefined array key”,
trim() - zdejmuje spacje z brzegów imion i nazwisk.
Nazwy zmiennych po angielsku ($ambulance, $rescuer1), klucze tablicy - takie, jak atrybuty name w formularzu.
R.5.4 Skrypt wysyła do bazy danych zmodyfikowane zapytanie 1, jego wartości wypełnione są danymi z formularza. Należy sprawdzić w phpMyAdmin czy rekord został wstawiony
ok. 3 min
Polecenie z arkusza
Skrypt wysyła do bazy danych zapytanie wstawiające rekord do tabeli ratownicy z danymi pobranymi z formularza (zmodyfikowane zapytanie 1, opisane w punkcie „Operacje na bazie danych”)
Zapytanie 1, w którym numer karetki i nazwiska zastępują parametry:ambulance, :rescuer1, :rescuer2, :rescuer3. Treść stoi w zmiennej $sql - przyda się w następnym kroku:
$pdo->prepare($sql) - przygotowanie zapytania z parametrami,
bindValue - wartość dla każdego parametru; numer karetki z typem PDO::PARAM_INT, więc trafi do zapytania jako liczba, nazwiska jako napisy,
execute() - wykonanie.
Dane nigdy nie staną się kodem SQL. Sprawdzone: nazwisko O'Neill, przydomek w cudzysłowie i wpisany w pole trzeciego ratownika fragment '), (NULL, 1, 'X', 'Y', 'Z') -- zapisały jeden rekord, z tym tekstem jako nazwiskiem. Sprawdzenie, jak każe klucz (R.5.4): formularz z danymi 7, Marek Lis, Ewa Sowa, Piotr Kos i w tabeli nowy wiersz 5.
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.
R.5.5 Skrypt wyświetla tekst: „Do bazy zostało wysłane zapytanie: <zapytanie>”, gdzie <zapytanie> oznacza treść zapytania, które zostało wysłane skryptem do bazy danych
ok. 4 min
Polecenie z arkusza
Skrypt wypisuje tekst: „Do bazy zostało wysłane zapytanie: <zapytanie>”, gdzie <zapytanie> oznacza treść zapytania, które zostało wysłane skryptem do bazy danych
Przy zapytaniu przygotowanym w kodzie nie ma gotowego tekstu z danymi - jest $sql z parametrami. Skąd wziąć „treść zapytania, które zostało wysłane”?
PDO dla MySQL i MariaDB domyślnie samo składa zapytanie przed wysłaniem: w miejsce parametru wstawia liczbę (PARAM_INT) albo napis w apostrofach, ze znakami ucieczki przed apostrofami i ukośnikami. Skrypt robi to samo jawnie:
$pdo->quote() - napis w apostrofach, zabezpieczony tak samo, jak robi to PDO przy bindValue,
(string) $ambulance - liczba bez apostrofów,
strtr podmienia w $sql nazwy parametrów na te wartości.
Sprawdzone w dzienniku serwera bazy (general log MariaDB): do bazy dotarło dokładnie INSERT INTO ratownicy VALUES (NULL, 7, 'Marek Lis', 'Ewa Sowa', 'Piotr Kos') - znak w znak to, co wypisuje skrypt; różni się tylko końcowy średnik, którego serwer nie zapisuje w dzienniku (R.5.5). To samo dla trudnych danych: O'Neill przyszło jako 'Ewa O\'Neill', a skrypt wypisał to samo.
Przed echo treść przechodzi przez e() - funkcję z htmlspecialchars. Zapytanie zawiera dane wpisane przez użytkownika, a <script> w nazwisku nie może wykonać się na stronie. Podgląd: wynik dla zespołu 7.
Typowe błędy
Gdyby w opcjach PDO wyłączyć składanie zapytań po stronie PHP (PDO::ATTR_EMULATE_PREPARES => false), baza dostałaby osobno treść z parametrami i osobno dane - wtedy uczciwą odpowiedzią na „wysłane zapytanie” jest sama treść $sql z parametrami.
Krok 42: 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, zapis i złożenie treści zapytania trafiają do bloku try, a komunikat - do zmiennej $message:
catch (PDOException $exception) - gdy baza nie działa albo zapytanie się nie powiedzie, $message dostaje zwykłe zdanie dla użytkownika zamiast komunikatu PHP z danymi serwera. Sprawdzone na złym haśle: skrypt wypisuje „Nie udało się dodać zespołu, spróbuj ponownie za chwilę.”,
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).
$query powstaje w try, przed zamknięciem - quote() potrzebuje otwartego połączenia. Wypisanie komunikatu jest już po finally. Podgląd: dla zespołu 7 bez zmian.
Krok 43: Strona z komunikatem w wyglądzie formularza
ok. 3 min
Dodatek spoza arkusza - klucz go nie ocenia. Sam tekst na białym tle wygląda jak błąd. Tu pod skryptem stoi krótka strona w tym samym wyglądzie co formularz (ten sam <header>, <main> i styl3.css): nagłówek, komunikat z $message przepuszczonym przez e() i odnośnik do formularza, żeby dodać kolejny zespół. Kod PHP zostaje na górze pliku, w HTML-u jest tylko jedno wypisanie zmiennej <?= e($message) ?>.
Krok 44: Zły numer karetki i puste pola nie trafiają do bazy
ok. 3 min
Pola mają required i min="1", ale to zabezpieczenie przeglądarki - dane da się wysłać z pominięciem formularza (np. poleceniem curl albo po usunięciu atrybutów w narzędziach przeglądarki). Dlatego skrypt sprawdza je jeszcze raz, zanim połączy się z bazą: gdy filter_var zwróciło false albo któreś nazwisko jest puste po trim(), zamiast zapisu ustawia komunikat z tym, co trzeba poprawić.
Sprawdzone: pusty numer, 0, 2.5 i nazwisko z samych spacji nie dodają rekordu. W wersji podstawowej pusty numer wywraca zapytanie (VALUES (NULL, , …). Podgląd: komunikat dla nazwiska ze spacji.
dodanie.phpPHPzmienione: 26 linii
<?phpfunctione(string $text): string{returnhtmlspecialchars($text, ENT_QUOTES, 'UTF-8');}if ($_SERVER['REQUEST_METHOD'] !== 'POST') {header('Location: ratownicy.html');exit;}$ambulance = filter_var($_POST['nrKaretki'] ?? '', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]);$rescuer1 = trim($_POST['ratownik1'] ?? '');$rescuer2 = trim($_POST['ratownik2'] ?? '');$rescuer3 = trim($_POST['ratownik3'] ?? '');$sql = 'INSERT INTO ratownicy VALUES (NULL, :ambulance, :rescuer1, :rescuer2, :rescuer3);';if ($ambulance === false || $rescuer1 === '' || $rescuer2 === '' || $rescuer3 === '') {$message = 'Wpisz numer karetki (liczba całkowita większa od zera) oraz imiona i nazwiska trzech ratowników.';} else {try {$pdo = new PDO('mysql:host=localhost;dbname=ee09;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, ]);$statement = $pdo->prepare($sql);$statement->bindValue('ambulance', $ambulance, PDO::PARAM_INT);$statement->bindValue('rescuer1', $rescuer1);$statement->bindValue('rescuer2', $rescuer2);$statement->bindValue('rescuer3', $rescuer3);$statement->execute();$query = strtr($sql, [':ambulance' => (string) $ambulance,':rescuer1' => $pdo->quote($rescuer1),':rescuer2' => $pdo->quote($rescuer2),':rescuer3' => $pdo->quote($rescuer3), ]);$message = 'Do bazy zostało wysłane zapytanie: ' . $query; } catch (PDOException $exception) {$message = 'Nie udało się dodać zespołu, spróbuj ponownie za chwilę.'; } finally {$statement = null;$pdo = null; }}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <sectionclass="left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionclass="middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionclass="right"> <imgsrc="obraz.jpg"alt="Ratownicy"width="167"height="100"> </section> </header> <main> <h3>Dodaj nowy zespół</h3> <p><?= e($message) ?></p> <ahref="ratownicy.html">Dodaj kolejny zespół</a> </main></body></html>
Podgląd strony po tym kroku (dodanie.php)
Krok 45: Odświeżenie po zapisie nie dodaje drugiego zespołu
ok. 4 min
Strona z komunikatem jest wynikiem żądania POST, więc odświeżenie (F5) pyta, czy wysłać dane ponownie - a ponowne wysłanie dopisałoby drugi identyczny zespół. 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 złożeniu komunikatu) i po bloku finally komunikat trafia do $_SESSION, a header('Location: dodanie.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 wysłanym zapytaniem, a kolejne odświeżenie - powrót do formularza, bez drugiego rekordu w tabeli. Błąd (zły numer) nie przekierowuje - komunikat zostaje na stronie. Podgląd: stan po przekierowaniu.
dodanie.phpPHPzmienione: 49 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: ratownicy.html');exit; }$message = $_SESSION['message'];unset($_SESSION['message']);} else {$ambulance = filter_var($_POST['nrKaretki'] ?? '', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]);$rescuer1 = trim($_POST['ratownik1'] ?? '');$rescuer2 = trim($_POST['ratownik2'] ?? '');$rescuer3 = trim($_POST['ratownik3'] ?? '');$sql = 'INSERT INTO ratownicy VALUES (NULL, :ambulance, :rescuer1, :rescuer2, :rescuer3);';if ($ambulance === false || $rescuer1 === '' || $rescuer2 === '' || $rescuer3 === '') {$message = 'Wpisz numer karetki (liczba całkowita większa od zera) oraz imiona i nazwiska trzech ratowników.'; } else {$saved = false;try {$pdo = new PDO('mysql:host=localhost;dbname=ee09;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, ]);$statement = $pdo->prepare($sql);$statement->bindValue('ambulance', $ambulance, PDO::PARAM_INT);$statement->bindValue('rescuer1', $rescuer1);$statement->bindValue('rescuer2', $rescuer2);$statement->bindValue('rescuer3', $rescuer3);$statement->execute();$query = strtr($sql, [':ambulance' => (string) $ambulance,':rescuer1' => $pdo->quote($rescuer1),':rescuer2' => $pdo->quote($rescuer2),':rescuer3' => $pdo->quote($rescuer3), ]);$message = 'Do bazy zostało wysłane zapytanie: ' . $query;$saved = true; } catch (PDOException $exception) {$message = 'Nie udało się dodać zespołu, spróbuj ponownie za chwilę.'; } finally {$statement = null;$pdo = null; }if ($saved) {// PRG: komunikat do sesji i przekierowanie - odświeżenie strony nie doda zespołu drugi raz$_SESSION['message'] = $message;header('Location: dodanie.php');exit; } }}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <sectionclass="left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionclass="middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionclass="right"> <imgsrc="obraz.jpg"alt="Ratownicy"width="167"height="100"> </section> </header> <main> <h3>Dodaj nowy zespół</h3> <p><?= e($message) ?></p> <ahref="ratownicy.html">Dodaj kolejny zespół</a> </main></body></html>
Podgląd strony po tym kroku (dodanie.php)
Etap 5: Porównanie z wersją podstawową
Krok 46 · po tym etapie masz 34 z 34 kryteriów (pkt)
Krok 46: Co jest inaczej i którą wersję wybrać na egzaminie
ok. 3 min
Obie wersje dają komplet 34 punktów. Różnice:
wersja podstawowa
wersja nowoczesna
bloki
siedem section z id jeden po drugim
header i footer z trzema section, main
układ
float: left i clear: both
header i footer jako display: flex, width na blokach
style bloków
sześć identyfikatorów w jednej regule
header section, footer section i klasy .left, .middle, .right
kolory
wpisane w każdej regule
zmienne --brown, --snow
formularz
napis, <br>, pole, input type="reset"
label for, wiersze w div, button, required, min
biblioteka
mysqli (tabela 1 arkusza)
PDO z wyjątkami
numer karetki
wklejony do zapytania, puste pole psuje składnię
filter_var - liczba całkowita od 1 albo komunikat
INSERT
dane wklejone w treść zapytania
parametry i bindValue
wypisane zapytanie
zmienna $query bez escapowania
ta sama treść, którą dostała baza, przez e()
zamknięcie bazy
mysqli_close na końcu
$pdo = null w finally
po zapisie
sam tekst, F5 dodaje drugi zespół
strona w wyglądzie formularza, przekierowanie
Na egzaminie wersja podstawowa trzyma się funkcji z tabeli 1 i łatwiej ją napisać bez dokumentacji. Nowoczesna nie wywraca się na apostrofie ani pustym numerze, nie da się jej wstrzyknąć kodu SQL ani skryptu i nie dubluje zespołów 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 47 · po tym etapie masz 34 z 34 kryteriów (pkt)
Krok 47: 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: dodanie.php, import.png, kw1.jpg - kw4.jpg, kwerendy.txt, obraz.jpg, przeglądarka.txt, ratownicy.html i styl3.css. 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.