Serwis używa plików cookies do analizy ruchu i poprawy działania. Szczegóły
EE.09-04-23.01-SGStyczeń 2023 · 48 kroków · ok. 93 min · 39 kryteriów z klucza
Rozwiązanie krok po kroku: Wizytówki pracowników z formularzem (Wersja podstawowa)
Aplikacja wizytówek pracowniczych: baza firma z tabelami pracownicy i stanowiska, na której cztery zapytania wybierają dane pracownika, osoby bez podpisanego dokumentu RODO i pracownika bez aktualnych badań urodzonego w latach 70., a ostatnie dodaje kolumnę umiejetnosci. Do tego zdjęcie zespołu przeskalowane do wysokości 200 px i strona index.php: baner z formularzem wyboru numeru pracownika, wizytówka ze zdjęciem i adresem wypisana przez skrypt PHP oraz trzy bloki stopki - w prawym lista osób proszonych o podpisanie dokumentu RODO.
To arkusz EE.09 ze stycznia 2023 - kwalifikacji formuły 2017, którą zastąpiła INF.03. Kroki idą zdanie po zdaniu za treścią arkusza - przy każdym jest polecenie z arkusza, a kod pokazuje dokładnie te linie, które je spełniają. PHP jest napisany najprościej, funkcjami z tabeli 1 arkusza (mysqli_connect, mysqli_query, mysqli_fetch_row, mysqli_close), a na końcu są trzy kroki o zabezpieczeniach, których klucz nie sprawdza - pokazane na prawdziwym ataku na ten skrypt.
To jest wersja podstawowa. W zakładce „Nowoczesny kod (flex, PDO)” jest drugi sposób rozwiązania tego samego arkusza: PDO z zapytaniem przygotowanym na górze pliku, walidacja numeru, stopka na flex i zmienne CSS - obie wersje są zgodne z kluczem.
Baza i grafiki pochodzą z oryginalnego archiwum CKE zad4 (załącznik do pobrania na stronie arkusza, hasło w treści zadania). 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.1.2 - użyte funkcje działają w obu wersjach).
Jak liczą się punkty. Klucz ma 39 kryteriów (R.1.1 - R.5.7), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 30 punktów (75% z 39 to 29,25, a punktów nie dzieli się na części). 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 39 kryteriów (pkt)
Krok 1: Folder zdającego i archiwum zad4
ok. 2 min
Polecenie z arkusza
Archiwum należy rozpakować. Na pulpicie konta Egzamin należy utworzyć folder. Jako nazwy folderu należy użyć numeru zdającego, którym został podpisany arkusz. Rozpakowane pliki należy umieścić w tym folderze. Zaleca się, aby rozpakowane pliki znajdowały się w tym samym folderze, co pliki strony. Po skończonej pracy wszystkie wyniki należy zapisać w tym folderze.
Na pulpicie tworzysz folder nazwany numerem PESEL - w tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora, Bartosz Bryniarski. Archiwum zad4.zip rozpakowujesz do tego folderu, podając hasło #WizyTowniK$ (wielkość liter i oba znaki specjalne mają znaczenie). W środku: baza.sql, obraz.jpg (zdjęcie zespołu do stopki) i zdjęcia pracowników 1.jpg - 9.jpg - nazwa pliku to numer pracownika w bazie, z tego skorzysta skrypt.
Strona jest w PHP, więc działa tylko przez serwer. Folder możesz skopiować do C:\xampp\htdocs albo pracować w nim i na koniec skopiować pliki z htdocs z powrotem - wyniki muszą trafić do folderu na pulpicie.
Krok 2: Pusta baza firma
ok. 2 min
Polecenie z arkusza
Za pomocą narzędzia phpMyAdmin wykonaj operacje na bazie danych: Utwórz bazę danych o nazwie firma
W XAMPP Control PanelStart przy Apache i MySQL, potem http://localhost/phpmyadmin. Nowa, nazwa firma, porównywanie np. utf8mb4_polish_ci (arkusz go nie narzuca), Utwórz.
Krok 3: Import pliku baza.sql i zrzut import.jpg
Kryteria:
R.1.1 Wykonano import tabel do bazy danych firma , czynność udokumentowano plikiem o nazwie import w formacie JPEG
ok. 3 min
Polecenie z arkusza
Do bazy firma zaimportuj tabele z pliku baza.sql z rozpakowanego archiwum. Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w formacie JPEG 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
Zaznacz bazę firma, karta Import, Wybierz plik → baza.sql, Wykonaj. Plik tworzy dwie tabele z obrazu 1: pracownicy (9 osób) i stanowiska (4 stanowiska). Na zrzucie widać komunikat o sukcesie i obie tabele w lewym panelu; tu dodatkowo otwarta jest tabela pracownicy. Zrzut całego ekranu z paskiem zadań zapisz jako import.jpg (JPEG - zrzuty zapytań będą w PNG).
Pola czyRODO i czyBadania przechowują 1 albo 0 (tak/nie) - przydadzą się w zapytaniach 2 i 3.
Typowe błędy
Zrzut w PNG albo nazwany inaczej niż import nie spełnia R.1.1. Wykadrowany zrzut nie jest oceniany.
Podgląd strony po tym kroku
Krok 4: Zapytanie 1: dane pracownika o id 1
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 wybierające jedynie pola id, imie, nazwisko, adres, miasto z tabeli pracownicy dla wiersza o id równym 1. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id, imie, nazwisko, adres, miasto FROM pracownicy WHERE id = 1; oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczny jest jedynie rekord z danymi: 1, Jan, Nowak, ul. Grottgera 5, Bytom
ok. 3 min
Polecenie z arkusza
Wykonaj zapytania SQL działające na bazie firma. Zapytania zapisz w pliku kwerendy.txt. Wykonaj zrzuty ekranu przedstawiające wyniki działania kwerend. Zrzuty zapisz w formacie PNG i nadaj im nazwy kw1, kw2, kw3, kw4. Zrzuty powinny obejmować cały ekran monitora z widocznym paskiem zadań. Zapytanie 1: wybierające jedynie pola id, imie, nazwisko, adres, miasto z tabeli pracownicy dla wiersza o id równym 1
Karta SQL bazy firma:
SELECT id, imie, nazwisko, adres, miasto - pięć pól z arkusza, w tej kolejności; skrypt będzie odczytywał je po numerach,
FROM pracownicy,
WHERE id = 1 - jeden wiersz.
Wynik: 1, Jan, Nowak, ul. Grottgera 5, Bytom. Zapytanie kopiujesz do kwerendy.txt (R.1.2), zrzut: kw1.png. To samo zapytanie, ze zmienionym numerem, wyśle skrypt 1.
kwerendy.txtTekstnowy plik
-- Zapytanie 1SELECT id, imie, nazwisko, adres, miasto FROM pracownicy WHERE id = 1;
Podgląd strony po tym kroku
Krok 5: Zapytanie 2: kto nie podpisał dokumentu RODO
Kryteria:
R.1.4 Utworzono zapytanie 2 wybierające jedynie pola imie, nazwisko z tabeli pracownicy dla pracowników, którzy nie podpisali dokumentu RODO. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, nazwisko FROM pracownicy WHERE czyRODO = false; (lub 0) oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczne są jedynie rekordy: Katarzyna, Kowalska; Krzysztof, Rostecki; Robert, Marcinkowski
ok. 2 min
Polecenie z arkusza
Zapytanie 2: wybierające jedynie pola imie, nazwisko z tabeli pracownicy dla pracowników, którzy nie podpisali dokumentu RODO
„Nie podpisał” to czyRODO = 0 (klucz przyjmuje też = false). Wynik: Katarzyna Kowalska, Krzysztof Rostecki, Robert Marcinkowski - te trzy osoby wypisze skrypt 2 w stopce. Zrzut: kw2.png.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT id, imie, nazwisko, adres, miasto FROM pracownicy WHERE id = 1;-- Zapytanie 2SELECT imie, nazwisko FROM pracownicy WHERE czyRODO = 0;
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: bez badań, urodzeni w latach 1970 - 1979
Kryteria:
R.1.5 Utworzono zapytanie 3 wybierające jedynie pola id, nazwisko z tabeli pracownicy dla pracowników bez aktualnych badań pracowniczych, którzy urodzili się w latach 1970 ÷ 1979. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id, nazwisko FROM pracownicy WHERE dataUr LIKE "197%" AND czyBadania = false; (lub 0); (możliwe też przez porównanie daty początkowej i końcowej) oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczny jest jedynie jeden rekord z danymi: 8, Maj
ok. 3 min
Polecenie z arkusza
Zapytanie 3: wybierające jedynie pola id, nazwisko z tabeli pracownicy dla pracowników bez aktualnych badań pracowniczych, którzy urodzili się w latach 1970 ÷ 1979
Dwa warunki naraz, więc AND:
czyBadania = 0 - brak aktualnych badań,
dataUr BETWEEN '1970-01-01' AND '1979-12-31' - data urodzenia w przedziale; BETWEEN obejmuje oba końce, więc 1 stycznia 1970 i 31 grudnia 1979 też się liczą. Daty zapisujesz jako tekst w formacie RRRR-MM-DD.
Klucz podaje też krótszy zapis dataUr LIKE '197%' - porównuje datę zamienioną na tekst z wzorcem „zaczyna się od 197”. Daje ten sam wynik, ale BETWEEN porównuje daty jako daty i może skorzystać z indeksu. Wynik: jeden pracownik - 8, Maj (Ewa Maj, ur. 28.02.1979). Zrzut: kw3.png.
Typowe błędy
BETWEEN 1970 AND 1979 bez cudzysłowów i miesięcy porównuje datę z liczbami i nie zwraca nikogo. Rok można też wyciągnąć funkcją: YEAR(dataUr) BETWEEN 1970 AND 1979.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT id, imie, nazwisko, adres, miasto FROM pracownicy WHERE id = 1;-- Zapytanie 2SELECT imie, nazwisko FROM pracownicy WHERE czyRODO = 0;-- Zapytanie 3SELECT id, nazwisko FROM pracownicy WHERE czyBadania = 0 AND dataUr BETWEEN '1970-01-01' AND '1979-12-31';
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: nowa kolumna umiejetnosci
Kryteria:
R.1.6 Utworzono zapytanie 4 wstawiające kolumnę umiejetnosci typu tekstowego do tabeli pracownicy . W pliku z kwerendami lub na zrzucie istnieje zapis np.: ALTER TABLE pracownicy ADD umiejetnosci TEXT; (lub ADD COLUMN; dowolny typ tekstowy) oraz wynik działania zapytania udokumentowano zrzutem wskazującym na poprawne dodanie kolumny
ok. 2 min
Polecenie z arkusza
Zapytanie 4: wstawiające kolumnę umiejetnosci typu tekstowego do tabeli pracownicy
Nowa kolumna to zmiana struktury: ALTER TABLE pracownicy ADD COLUMN umiejetnosci TEXT (słowo COLUMN można pominąć). TEXT to typ tekstowy bez podawania długości - pasuje do listy umiejętności, która bywa długa; klucz przyjmuje dowolny typ tekstowy, np. VARCHAR(255). Nazwa bez polskich liter. Na zrzucie kw4.png (karta Struktura) nowa kolumna jest dziesiąta, na końcu tabeli. kwerendy.txt ma komplet.
Typowe błędy
INSERT wstawia wiersze, a nie kolumny - „wstawiające kolumnę” w arkuszu to ALTER TABLE ... ADD.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT id, imie, nazwisko, adres, miasto FROM pracownicy WHERE id = 1;-- Zapytanie 2SELECT imie, nazwisko FROM pracownicy WHERE czyRODO = 0;-- Zapytanie 3SELECT id, nazwisko FROM pracownicy WHERE czyBadania = 0 AND dataUr BETWEEN '1970-01-01' AND '1979-12-31';-- Zapytanie 4ALTER TABLE pracownicy ADD COLUMN umiejetnosci TEXT;
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 8-24 · po tym etapie masz 19 z 39 kryteriów (pkt)
Krok 8: Grafika: wysokość 200 px z zachowaniem proporcji
Kryteria:
R.2.1 Plik obraz .jpg przeskalowano z zachowaniem proporcji do wysokości 200 px odpowiadająca temu szerokość wynosi 300 px (± 5 px)
ok. 2 min
Polecenie z arkusza
Plik obraz.jpg, wypakowany z archiwum, należy przeskalować z zachowaniem proporcji do wysokości 200 px
Oryginał ma 640 × 426 px. W GIMP-ie Obraz → Skaluj obraz, łańcuch między szerokością a wysokością zamknięty (to jest „zachowanie proporcji”), wysokość 200 - szerokość wyliczy się sama: 640 × 200 / 426 ≈ 300 px (klucz dopuszcza 300 ± 5 px). Plik → Nadpisz obraz.jpg.
Zdjęć pracowników 1.jpg - 9.jpg nie zmieniasz - ich rozmiar w wizytówce ustawi CSS.
Typowe błędy
Wpisanie 200 przy otwartym łańcuchu zostawi szerokość 640 px - zdjęcie będzie spłaszczone, a R.2.1 niespełnione.
Podgląd strony po tym kroku
Krok 9: Plik index.php w HTML5
Kryteria:
R.2.2 Witrynę internetową zapisano w pliku PHP o nazwie index
ok. 2 min
Polecenie z arkusza
Składa się ze strony o nazwie index.php. Zapisana w języku HTML5
Plik index.php (R.2.2) - rozszerzenie .php, bo strona będzie zawierać skrypty, choć na początku to czysty HTML. Pierwsza linia <!DOCTYPE html> to deklaracja HTML5. Plik bez ani linijki PHP podgląd pokazuje wprost; wynik działania PHP pojawi się od etapu skryptów.
Jawnie zastosowany właściwy standard kodowania polskich znaków
<meta charset="UTF-8"> jako pierwszy element <head>; plik zapisz w UTF-8. Dane z bazy też są w UTF-8 (utf8mb4 w baza.sql), więc polskie litery z tabeli wyświetlą się poprawnie.
R.2.3 Zastosowano deklarację języka HTML5, jawnie zapisany standard kodowania polskich znaków oraz zadeklarowano język witryny (np. <html lang = 'pl'>)
ok. 1 min
Polecenie z arkusza
Zadeklarowany język zawartości witryny: polski
lang="pl" w znaczniku <html>. Deklaracja HTML5, kodowanie i język razem dają R.2.3.
R.3.6 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl4.css , formatowanie pochodzi jedynie z tego arkusza Uwaga: kryterium to nie jest spełnione również, gdy zdający źle przypisał co najmniej jeden selektor do bloku (np. kropka zamiast #)
ok. 1 min
Polecenie z arkusza
Arkusz stylów w pliku o nazwie styl4.css prawidłowo połączony z kodem strony
<link rel="stylesheet" href="styl4.css">. Całe formatowanie trafi do tego pliku (R.3.6) - także pseudoklasa :hover przycisku.
Typowe błędy
Atrybut style w znaczniku albo blok <style> odbiera R.3.6; tak samo zły selektor bloku (np. .card zamiast #card).
Krok 14: Bloki: baner, wizytówka i trzy bloki stopki
Kryteria:
R.2.5 Wygląd strony zdefiniowano dzieląc ją na bloki: baner, wizytówki, trzy bloki stopki. Zastosowano znaczniki sekcji
ok. 2 min
Polecenie z arkusza
Podział strony na: blok banera, blok wizytówki, obok siebie trzy bloki stopki. Podział zrealizowany za pomocą znaczników sekcji tak, aby wygląd układu bloków strony po uruchomieniu w przeglądarce, był zgodny z Obrazem 2
Pięć bloków ze znaczników sekcji HTML5 (R.2.5):
<header> - baner,
<section id="card"> - blok wizytówki (identyfikatory po angielsku, arkusz ich nie narzuca),
trzy znaczniki <footer> z identyfikatorami footer-left, footer-middle, footer-right - stopka na obrazie 2 to trzy osobne bloki stojące obok siebie. Obok siebie ustawi je dopiero CSS.
Krok 16: Formularz wysyłający metodą POST do tego samego pliku
Kryteria:
R.3.3 Zdefiniowano wysyłanie danych z formularza do tego samego pliku metodą POST (poprawne również bez atrybutu action)
ok. 2 min
Polecenie z arkusza
formularz wysyłający dane metodą bezpieczną do tego samego pliku, zawierający:
<form method="post"> - bez atrybutu action formularz wysyła dane pod adres bieżącej strony, czyli do index.php (można też wpisać action="index.php"; klucz przyjmuje obie formy, R.3.3).
Arkusz i klucz przez „metodę bezpieczną” rozumieją POST: wysłany numer nie pojawia się w adresie strony. W terminologii protokołu HTTP słowo „bezpieczna” ma inne znaczenie - metodami bezpiecznymi (ang. safe) nazywa się te, które tylko odczytują dane, i jest nią właśnie GET. Do odczytu wizytówki GET byłby naturalniejszy (adres index.php?id=5 dałoby się zapisać w zakładkach), ale na egzaminie liczy się klucz - wpisz post.
Typowe błędy
method="get" - formularz zadziała, ale R.3.3 wymaga POST.
Krok 17: Pole numeryczne 1 - 9 z wartością początkową 1
Kryteria:
R.3.4 Zdefiniowano typ numeryczny dla pola edycyjnego oraz wartości: minimalną 1, maksymalną 9 oraz początkową 1
ok. 2 min
Polecenie z arkusza
pole edycyjne o wartości początkowej 1, przyjmujące tylko wartości liczbowe z przedziału od 1 do 9
<input> z czterema atrybutami (R.3.4):
type="number" - pole liczbowe ze strzałkami; przeglądarka nie przyjmie liter,
min="1" i max="9" - przedział; przy próbie wysłania 10 przeglądarka pokaże dymek z błędem i niczego nie wyśle,
value="1" - wartość na start.
Atrybut name="id" nadaje nazwę, pod którą wartość trafi do skryptu PHP ($_POST['id']) - bez name pole w ogóle nie jest wysyłane.
Typowe błędy
Ograniczenia min i max sprawdza tylko przeglądarka - w etapie dobrych praktyk widać, co się dzieje, gdy ktoś wyśle formularz z pominięciem przeglądarki.
R.2.9 W bloku banera umieszczono formularz z polem edycyjnym i przyciskiem
R.3.5 Przycisk wysyła dane z formularza (input lub button z typem submit, lub button bez typu)
ok. 1 min
Polecenie z arkusza
przycisk o treści „WYŚWIETL”, którego wciśnięcie powoduje wysłanie danych do skryptu PHP
<button type="submit"> wysyła formularz (R.3.5; przycisk bez typu w formularzu też wysyła). Napis wielkimi literami jak w arkuszu. Baner ma komplet: nagłówek i formularz z polem i przyciskiem (R.2.9).
Zawartość bloku wizytówek: efekt działania skryptu 1
Zawartość wizytówki (zdjęcie, imię i nazwisko, adres) wypisze skrypt PHP z danych z bazy - w HTML-u blok #card zostaje na razie pusty. Skrypt powstanie po stylach.
R.2.8 W lewym bloku stopki umieszczono obraz o nazwie obraz.jpg z tekstem alternatywnym "pracownicy firmy" lub w bloku wizytówki umieszczono obraz z tekstem alternatywnym "pracownik" (w skrypcie lub HTML)
ok. 1 min
Polecenie z arkusza
Zawartość lewego bloku stopki: obraz o nazwie obraz.jpg z tekstem alternatywnym „pracownicy firmy”
<img> z src i alt (R.2.8). To przeskalowane zdjęcie 300 × 200 px - tak wysokie jak blok stopki.
R.3.2 Na stronie umieszczono odnośnik, którego kliknięcie inicjuje otwarcie strony http://agencjareklamowa543.pl/ (opcjonalnie https://agencjareklamowa543.pl/) w nowej karcie przeglądarki
ok. 1 min
Polecenie z arkusza
Odnośnik do strony http://agencjareklamowa543.pl/ otwierający się w osobnej karcie przeglądarki i podpisany „Zobacz nasze realizacje”
<a> z pełnym adresem i target="_blank" - osobna karta (R.3.2).
Kroki 25-34 · po tym etapie masz 30 z 39 kryteriów (pkt)
Krok 25: Plik styl4.css: krój i tło strony
ok. 1 min
Polecenie z arkusza
Styl CSS powinien być zdefiniowany jedynie w zewnętrznym pliku CSS. Dla selektora strony: krój czcionki Arial, kolor tła AntiqueWhite
Nowy plik styl4.css. Selektor strony body: krój Arial i tło AntiqueWhite - nazwa koloru CSS, jasny beż z obrazu 2.
styl4.cssCSSnowy plik
body {font-family: Arial;background-color: AntiqueWhite;}
Podgląd strony po tym kroku (index.php)
Krok 26: Baner
ok. 1 min
Polecenie z arkusza
Dla bloku banera: kolor tła #7B5E57, biały kolor czcionki, wyrównanie tekstu do środka
Selektor header. text-align: center środkuje nagłówek i formularz - pole i przycisk są elementami liniowymi, więc ustawiają się jak tekst.
styl4.cssCSSzmienione: 5 linii
body {font-family: Arial;background-color: AntiqueWhite;}header {background-color: #7B5E57;color: white;text-align: center;}
Podgląd strony po tym kroku (index.php)
Krok 27: Blok wizytówki
Kryteria: ,
R.4.6 Ustawiono wyrównanie tekstu do środka dla banera i bloku wizytówki
R.4.8 Ustawiono dla bloku wizytówki cień o cechach: przesunięcie poziome i pionowe 0, rozmycie 20px kolor szary (dowolny odcień) np. box-shadow: 0 0 20px grey; (lub 0 0 20px 0 grey, lub gray, lub inny dowolny szary)
ok. 3 min
Polecenie z arkusza
Dla bloku wizytówki: kolor czcionki #5D4037, maksymalna szerokość 300 px, wyrównanie tekstu do środka, marginesy zewnętrzne dolny i górny 70px, boczne ustalane automatycznie przez przeglądarkę, margines wewnętrzny dolny 60 px, cień bloku bez przesunięcia pionowego i poziomego, rozmycie 20 px i kolor szary
Selektor #card:
max-width: 300px - na szerokim ekranie 300 px, na wąskim (telefon) blok się zwęzi,
margin: 70px auto - skrót dwóch wartości: pierwsza to góra i dół (70 px), druga to boki; auto dzieli wolne miejsce po równo, więc wizytówka stoi na środku strony,
padding-bottom: 60px - pusty pas pod adresem (obraz 2),
box-shadow: 0 0 20px gray - oba przesunięcia 0, więc cień rozlewa się równo dookoła bloku; rozmycie 20 px, kolor szary (R.4.8).
Banner i wizytówka mają wyrównanie do środka (R.4.6).
Typowe błędy
margin: 70px bez auto przyklei wizytówkę do lewej. width: 300px zamiast max-width daje ten sam obraz na komputerze, ale klucz (R.4.5) wymaga maksymalnej szerokości.
R.4.2 Ustawiono kolor tła: #7B5E57 dla bloku banera i trzech bloków stopki
R.4.3 Ustawiono biały kolor czcionki dla bloku banera, trzech bloków stopki oraz #5D4037 dla bloku wizytówki
R.4.4 Ustawiono wysokość 200px dla trzech bloków stopki
R.4.5 Ustawiono szerokość dla bloków lewego i prawego stopki 33%,dla bloku środkowego stopki 34% oraz maksymalną szerokość (max-width) 300px dla bloku wizytówki
ok. 2 min
Polecenie z arkusza
Dla bloku środkowego stopki: kolor tła #7B5E57, biały kolor czcionki, wysokość 200 px, szerokość 34%
Ta sama reguła z szerokością 34% - razem 33 + 34 + 33 = 100%, bloki wypełnią całą szerokość strony. Tło (R.4.2), biały tekst stopki i banera oraz brązowy tekst wizytówki (R.4.3), wysokość 200 px (R.4.4) i szerokości z maksymalną szerokością wizytówki (R.4.5) są ustawione.
Bloki stoją jeszcze jeden pod drugim - obok siebie ustawi je reguła układu na końcu pliku.
R.4.9 Ustawiono styl wyłącznie dla obrazu w bloku wizytówki szerokość 100%, margines wewnętrzny dolny (padding-bottom) 20 px
ok. 1 min
Polecenie z arkusza
Dla obrazu znajdującego się w wizytówce (obraz w stopce nie jest formatowany tym stylem): szerokość 100%, margines wewnętrzny dolny 20 px
Selektor potomka #card img - tylko obraz wewnątrz wizytówki; samo img objęłoby też zdjęcie w stopce i rozciągnęło je (R.4.9). Zdjęcie pracownika 400 × 267 px zmieści się w 300 px szerokości bloku.
Typowe błędy
Selektor img bez #card - klucz wymaga stylu wyłącznie dla obrazu w wizytówce.
R.4.1 Ustawiono dla selektora strony (body lub html, lub kontenera strony) krój czcionki Arial, kolor tła AntiqueWhite oraz dla selektora h1 grubość czcionki na 300
ok. 1 min
Polecenie z arkusza
Dla selektora nagłówka pierwszego stopnia: grubość czcionki 300
Selektor znacznika h1 - arkusz w uwadze zabrania tu klasy i identyfikatora. font-weight: 300 to krój cieńszy od zwykłego (400), a nagłówki domyślnie mają 700 (pogrubienie). Z regułą strony daje to R.4.1.
R.4.7 Ustawiono marginesy zewnętrzne (margin) dolny i górny: 70px, boczne: auto dla bloku wizytówki; 5px dla selektora pola edycyjnego i przycisku oraz marginesy wewnętrzne (padding) 10px dla selektora pola edycyjnego i przycisku, margines wewnętrzny dolny (padding-bottom) 60px dla bloku wizytówki
ok. 2 min
Polecenie z arkusza
Dla selektora pola edycyjnego i przycisku: kolor tła #7B5E57, biały kolor czcionki, marginesy wewnętrzne 10 px, zewnętrzne 5 px, obramowanie 1 px, linią ciągłą białą
Selektory znaczników input, button - też narzucone w uwadze arkusza. Pole i przycisk mają tło banera i białą ramkę, więc na obrazie 2 widać je jako dwa jasne prostokąty. Marginesy wizytówki, pola i przycisku są ustawione (R.4.7).
R.4.10 Ustawiono dla pola edycyjnego i przycisku obramowanie 1px solid white; tło #7B5E57 i biały kolor czcionki oraz jedynie dla przycisku pseudoklasę hover z wartościami: tło białe, kolor czcionki #7B5E57
ok. 1 min
Polecenie z arkusza
Gdy kursor myszy znajdzie się w obrębie przycisku, tło przycisku zmienia się na białe, a kolor czcionki na #7B5E57
Pseudoklasa :hover tylko dla button - pole liczbowe ma się nie zmieniać (R.4.10). Reguła stoi po regule input, button, a przy tej samej sile selektorów wygrywa reguła zapisana później - tu i tak button:hover jest silniejszy od samego button.
Typowe błędy
input:hover, button:hover zmieni też pole - klucz wymaga pseudoklasy jedynie dla przycisku.
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ł strony na: blok banera, blok wizytówki, obok siebie trzy bloki stopki. Podział zrealizowany za pomocą znaczników sekcji tak, aby wygląd układu bloków strony po uruchomieniu w przeglądarce, był zgodny z Obrazem 2
float: left na trzech blokach stopki - ustawiają się w rzędzie od lewej. Szerokości dają razem dokładnie 100%, więc trzeci blok mieści się jeszcze w rzędzie (bloki nie mają marginesów ani obramowań, które by do tego doszły). Baner i wizytówka są zwykłymi blokami nad stopką (R.3.1). Pod stopką nie ma treści, więc clear nie jest potrzebny.
Typowe błędy
Dodanie stopce padding albo border przy szerokościach 33/34/33% zepchnie prawy blok do nowego wiersza - wtedy pomaga box-sizing: border-box.
Kroki 35-44 · po tym etapie masz 39 z 39 kryteriów (pkt)
Krok 35: Skrypt 1 w bloku wizytówki: połączenie z bazą firma
Kryteria:
R.5.1 Skrypt realizuje połączenie z serwerem bazy danych i wybór bazy firma
ok. 3 min
Polecenie z arkusza
Napisany w języku PHP. Skrypt łączy się z serwerem bazy danych na localhost, użytkownik root bez hasła, baza danych o nazwie firma
„Zawartość bloku wizytówek: efekt działania skryptu 1” - blok PHP (<?php ... ?>) piszesz więc wewnątrz <section id="card">. Serwer wykona go, zanim strona trafi do przeglądarki, a w jego miejsce wstawi to, co skrypt wypisze.
Pierwsza instrukcja: mysqli_connect z tabeli 1 - serwer localhost, użytkownik root, puste hasło '' i baza firma (R.5.1). Połączenie trafia do zmiennej $connection; skorzysta z niej też skrypt 2 w stopce - zmienne PHP z jednego bloku <?php są widoczne w kolejnych blokach tego samego pliku.
Od tego kroku podgląd to wynik działania strony po stronie serwera (prawdziwe uruchomienie w PHP 8.2). Stronę otwierasz przez http://localhost/…/index.php - otwarty z dysku plik PHP nie zostanie wykonany.
Działanie skryptu 1: wysyła do bazy zapytanie 1 zmodyfikowane w ten sposób, że dane wybrane kwerendą po uruchomieniu strony WWW dotyczą pracownika o id równym 1, po zatwierdzeniu formularza, pracownika o id wpisanym do pola edycyjnego
Najpierw sama pierwsza część zdania - pracownik numer 1:
mysqli_query($connection, '...') - zapytanie 1 z kwerendy.txt, wynik w $result,
mysqli_fetch_row($result) - pierwszy (i jedyny) wiersz wyniku jako tablica numerowana od zera: $row[0] to id, $row[1] - imie, $row[2] - nazwisko, $row[3] - adres, $row[4] - miasto. Kolejność jest taka jak pól w SELECT.
Skrypt jeszcze niczego nie wypisuje - podgląd się nie zmienia. Numer z formularza dojdzie po wypisaniu wizytówki.
Krok 37: Zdjęcie pracownika: nazwa pliku z pola id
Kryteria:
R.5.5 W skrypcie 1 ustalono nazwę pliku na podstawie wartości id pracownika zwróconej zapytaniem np. $wiersz[0] = (string) $wiersz[0] . ".jpg"; oraz wyświetlono obraz o takiej nazwie pliku
ok. 3 min
Polecenie z arkusza
dane otrzymane z bazy są wyświetlane według schematu: obraz z tekstem alternatywnym „pracownik” i nazwą pliku <id>.jpg, gdzie <id> to pole id wybrane z bazy
$file = $row[0] . '.jpg'; - kropka w PHP skleja napisy: id 1 i .jpg dają 1.jpg (R.5.5),
echo wypisuje znacznik <img> z tą nazwą i tekstem alternatywnym „pracownik”. Cudzysłowy atrybutów wewnątrz napisu w cudzysłowach poprzedzasz ukośnikiem \" - inaczej PHP uznałby, że napis się kończy. W napisie w cudzysłowach podwójnych PHP sam wstawia wartość zmiennej $file.
Podgląd: zdjęcie Jana Nowaka (1.jpg) w wizytówce, rozciągnięte do jej szerokości przez CSS.
Typowe błędy
Napis w apostrofach '<img src="$file">' nie podstawia zmiennych - przeglądarka dostanie dosłownie $file i nie znajdzie pliku.
Krok 38: Imię i nazwisko w nagłówku drugiego stopnia
ok. 2 min
Polecenie z arkusza
nagłówek drugiego stopnia z imieniem i nazwiskiem wybranymi z bazy
echo "<h2>$row[1] $row[2]</h2>"; - imię, spacja, nazwisko. W napisie w cudzysłowach PHP podstawia też elementy tablicy zapisane bez apostrofów wokół indeksu, np. $row[1].
R.5.3 Skrypt 2 wysyła do bazy zapytanie 2 lub skrypt 1 wysyła do bazy zmodyfikowane zapytanie 1 w ten sposób, że dane wybrane kwerendą po uruchomieniu strony WWW dotyczą pracownika o id równym 1, natomiast po zatwierdzeniu formularza, pracownika o id wpisanym do pola edycyjnego formularza
ok. 3 min
Polecenie z arkusza
Działanie skryptu 1: wysyła do bazy zapytanie 1 zmodyfikowane w ten sposób, że dane wybrane kwerendą po uruchomieniu strony WWW dotyczą pracownika o id równym 1, po zatwierdzeniu formularza, pracownika o id wpisanym do pola edycyjnego
Teraz druga część zdania:
$id = 1; - wartość domyślna, gdy strona jest otwierana pierwszy raz,
isset($_POST['id']) jest prawdziwe dopiero po kliknięciu „WYŚWIETL” - wtedy $id dostaje numer z pola o nazwie id,
zapytanie przechodzi do cudzysłowów podwójnych i zamiast 1 ma $id - PHP wstawi tam liczbę przed wysłaniem zapytania do bazy (R.5.3).
Podgląd: formularz wysłany z numerem 8 - wizytówka Ewy Maj (8.jpg). Pole w banerze znów pokazuje 1, bo value="1" jest wpisane na stałe; arkusz nie wymaga, żeby wybrany numer w nim został (wersja nowoczesna go zostawia).
Typowe błędy
Zapytanie w apostrofach ('... WHERE id = $id;') wyśle do bazy dosłownie $id i skończy się błędem składni SQL.
Skrypt 2 wysyła do bazy zapytanie 2 i wypisuje imiona i nazwiska wybrane zapytaniem jako osobne elementy listy
Drugi blok PHP stoi wewnątrz <ol> - wypisane elementy <li> trafią do listy. Korzysta z połączenia $connection otwartego przez skrypt 1 i wysyła zapytanie 2 z kwerendy.txt. Zmienna $result dostaje nowy wynik - poprzedni (wiersz pracownika) już nie jest potrzebny.
R.2.7 W bloku stopki umieszczono listę numerowaną, zastosowano znaczniki <ol>, <li> (w skrypcie lub HTML)
R.5.6 W skrypcie 2 zastosowano pętlę działającą na wszystkich wierszach wybranych zapytaniem
R.5.7 Skrypt 2 wypisuje imiona i nazwiska wybrane zapytaniem jako osobne elementy listy
ok. 3 min
Polecenie z arkusza
Skrypt 2 wysyła do bazy zapytanie 2 i wypisuje imiona i nazwiska wybrane zapytaniem jako osobne elementy listy
while ($row = mysqli_fetch_row($result)) - w każdym obrocie pętli kolejny wiersz wyniku; gdy wierszy zabraknie, funkcja zwraca null i pętla się kończy. Pętla przechodzi przez wszystkie wiersze wyniku (R.5.6),
echo "<li>$row[0] $row[1]</li>"; - imię i nazwisko jako osobny element listy (R.5.7, R.2.7 - znaczniki <ol> i <li>).
Podgląd: w prawym bloku stopki trzy ponumerowane osoby - Katarzyna Kowalska, Krzysztof Rostecki, Robert Marcinkowski - jak na obrazie 2.
R.5.2 Ostatnią operacją na bazie jest jej zamknięcie (zgodne ze składnią)
ok. 1 min
Polecenie z arkusza
Po wykonaniu operacji na bazie danych skrypt zamyka połączenie z serwerem
mysqli_close($connection) po pętli w skrypcie 2 - to ostatnia operacja na bazie na całej stronie (R.5.2). Zamknięcie w skrypcie 1 odcięłoby połączenie, zanim skrypt 2 zdąży wysłać zapytanie. Strona spełnia wszystkie kryteria arkusza; podgląd jak na obrazie 2. Dalej trzy kroki o zabezpieczeniach - klucz ich nie wymaga.
Typowe błędy
mysqli_close na końcu skryptu 1 sprawia, że mysqli_query w skrypcie 2 dostaje zamknięte połączenie - PHP 8 kończy się wtedy błędem.
Kroki 45-47 · po tym etapie masz 39 z 39 kryteriów (pkt)
Krok 45: Zabezpieczenie: numer z formularza sprawdzony w PHP
ok. 4 min
Polecenie z arkusza
pole edycyjne o wartości początkowej 1, przyjmujące tylko wartości liczbowe z przedziału od 1 do 9
Atrybuty type="number", min i max sprawdza przeglądarka. Formularz można wysłać z jej pominięciem (wystarczy polecenie curl albo narzędzia programisty), a skrypt wkleja tekst z pola wprost w zapytanie - to SQL injection. Sprawdzone na wersji z poprzednich kroków, w polu id wysłano:
Pracownika o id 0 nie ma, a UNION dokleja wiersz zbudowany przez atakującego: wizytówka pokazała daty urodzenia wszystkich dziewięciu pracowników - dane osobowe, których strona nigdy nie miała wyświetlać (tak samo da się wyciągnąć informację o badaniach lekarskich). Tekst abc kończy się wyjątkiem mysqli_sql_exception i „Fatal error” zamiast strony, a numer 12 - ostrzeżeniami PHP i pustą wizytówką.
Pierwsza poprawka to sprawdzenie danych na serwerze:
(int) zamienia tekst na liczbę całkowitą - z 0 UNION SELECT… zostaje 0, z abc też 0,
numer spoza przedziału 1 - 9 z arkusza zamienia się na domyślne 1.
Podgląd: ten sam atak po poprawce - wizytówka Jana Nowaka, żadne dane nie wyciekły. Stara linia zostaje w komentarzu. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
Działanie skryptu 1: wysyła do bazy zapytanie 1 zmodyfikowane w ten sposób, że dane wybrane kwerendą po uruchomieniu strony WWW dotyczą pracownika o id równym 1, po zatwierdzeniu formularza, pracownika o id wpisanym do pola edycyjnego
Sprawdzenie numeru zamknęło dziurę, ale zapytanie nadal powstaje ze sklejania tekstu - wystarczy, że ktoś później usunie linię z (int) albo skopiuje to zapytanie w miejsce, gdzie trafia napis, i atak wraca. Zasada, która działa zawsze: dane nigdy nie wchodzą do treści zapytania.
mysqli_prepare - zapytanie ze znakiem ? w miejscu numeru; baza sprawdza jego składnię, zanim zobaczy dane,
mysqli_stmt_bind_param($statement, 'i', $id) - podstawienie wartości; 'i' znaczy liczba całkowita (s - napis, d - liczba z przecinkiem),
mysqli_stmt_execute wykonuje zapytanie, a mysqli_stmt_get_result oddaje zwykły wynik - dalsza część skryptu z mysqli_fetch_row zostaje bez zmian.
Zapytanie 2 w skrypcie 2 nie zawiera żadnych danych od użytkownika, więc może zostać zwykłym mysqli_query. Podgląd: pracownik nr 5, Joanna Nowakowska - strona działa jak wcześniej.
Typowe błędy
Liczba liter w drugim argumencie mysqli_stmt_bind_param musi równać się liczbie znaków ? i liczbie zmiennych.
Krok 47: Zabezpieczenie: htmlspecialchars przy wypisywaniu danych z bazy
ok. 4 min
Polecenie z arkusza
dane otrzymane z bazy są wyświetlane według schematu
Dane w bazie wpisują ludzie - kadry, inny formularz, a kolumnę umiejetnosci z zapytania 4 mogą wypełniać sami pracownicy. Gdy w polu znajdzie się znacznik, echo wstawia go do strony jako kod. Sprawdzone na kopii bazy, w której adres Roberta Marcinkowskiego (nr 7) zawierał dopisek ze znacznikiem <script>: wersja z poprzednich kroków wykonała ten skrypt u każdego, kto otworzył wizytówkę, i podmieniła całą stronę - to atak XSS (wstrzyknięcie skryptu).
htmlspecialchars zamienia znaki <, >, & i cudzysłowy na encje (< itd.), więc przeglądarka pokazuje je jako tekst. Używa się jej na wyjściu, przy każdym wypisaniu danych, które nie pochodzą z kodu strony: imię i nazwisko, adres i miasto w skrypcie 1 oraz elementy listy w skrypcie 2. Numer pliku zdjęcia jest liczbą z bazy, a nagłówek „Adres:” stałym tekstem - tych nie trzeba.
Podgląd: ta sama kopia bazy po poprawce - znacznik widać w wizytówce jako zwykły tekst, strona działa. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
Krok 48 · po tym etapie masz 39 z 39 kryteriów (pkt)
Krok 48: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
Po zakończeniu pracy utwórz w folderze z numerem, którym został podpisany arkusz, 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 sprawdzana była strona. Jeśli pracujesz w C:\xampp\htdocs, skopiuj index.php i styl4.css z powrotem do folderu zdającego.
W folderze muszą być zdjęcia 1.jpg - 9.jpg oraz import.jpg, index.php, kw1.png, kw2.png, kw3.png, kw4.png, kwerendy.txt, obraz.jpg, przeglądarka.txt i styl4.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.