INF.03-04-24.06-SGCzerwiec 2024 · 46 kroków · ok. 76 min · 37 kryteriów z klucza
Rozwiązanie krok po kroku: Galeria zdjęć z bazą (Wersja podstawowa)
Galeria zdjęć to baza galeria (autorzy i ich zdjęcia, relacja 1..n) z czterema zapytaniami - warunek na liczbie polubień, złączenie JOIN z sortowaniem, COUNT z GROUP BY i ALTER TABLE dodający kolumnę - oraz zdjęcie przeskalowane w edytorze grafiki i strona galeria.php z trzema blokami. Skrypt 1 wypełnia środkowy blok zdjęciami z bazy: każde zdjęcie ma ukryty tytuł, autora i odnośnik „Pobierz”, które pokazują się po najechaniu kursorem (przezroczystość opacity, pozycjonowanie absolute względem bloku i płynne przejście transition). Skrypt 2 pokazuje w prawym bloku zdjęcie z co najmniej stu polubieniami.
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ą. Skrypty są najpierw napisane najprościej, funkcjami z tabeli 1 arkusza (mysqli_query, mysqli_fetch_row), a na końcu przerobione na wersję z prawdziwych projektów: kolumny po nazwach, htmlspecialchars w atrybutach, Skrypt 2 odporny na brak zdjęcia ze stu polubieniami i opis dostępny także z klawiatury.
To jest wersja podstawowa. W zakładce „Nowoczesny kod (grid, PDO)” jest drugi sposób rozwiązania tego samego arkusza: bloki na siatce CSS, kolory w zmiennych, karty zdjęć jako <figure> i PHP na PDO z danymi pobranymi przed HTML-em - obie wersje są zgodne z kluczem.
Baza i zdjęcia pochodzą z prawdziwego archiwum pliki4 (załącznik do arkusza, hasło w treści zadania). Zrzuty wyników zapytań są odtworzone z tej bazy - na egzaminie robisz je sam, z całego ekranu. Podgląd strony od kroków z PHP to wynik prawdziwego uruchomienia kodu z danego kroku w PHP 8.2 na bazie z arkusza.
Jak liczą się punkty. Klucz ma 37 kryteriów (R.1.1 - R.5.9), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 28 punktów - można stracić 9 kryteriów i nadal zdać. Przy każdym kroku jest napisane, które kryteria spełnia; egzaminator ocenia spełnienie kryteriów z klucza, nie zgodność z tym kodem.
Suwak i strzałki obok niego - albo ←→ na klawiaturze - przechodzą krok po kroku; wyjaśnienie, pliki i podgląd zmieniają się razem z krokiem.
Lista „Etap” przenosi od razu do wybranego etapu.
„Rozwiązuję samodzielnie” chowa rozwiązanie kroku - najpierw własna próba, potem odsłonięcie.
„Tryb prezentacji” pokazuje same kroki, bez menu strony - na rzutnik.
Etap 1: Baza danych
Kroki 1-7 · po tym etapie masz 6 z 37 kryteriów (pkt)
Krok 1: Baza danych galeria
ok. 2 min
Polecenie z arkusza
Utwórz bazę danych o nazwie galeria, z zestawem polskich znaków (np. utf8_unicode_ci)
Najpierw archiwum pliki4.zip z pulpitu (hasło (G@LeriA) razem z nawiasami okrągłymi) i folder z numerem zdającego, do którego trafiają rozpakowane pliki - arkusz zaleca, żeby zdjęcia leżały obok pliku strony. W phpMyAdmin: Nowa, nazwa galeria, porównywanie utf8_unicode_ci.
Krok 2: Import tabel z pliku baza.sql
ok. 2 min
Polecenie z arkusza
Do bazy zaimportuj tabele z pliku baza.sql z rozpakowanego archiwum
Zaznaczona baza galeria, potem Import → baza.sql → Wykonaj. Powstają dwie tabele z obrazu 1: autorzy (11 osób) i zdjecia (12 zdjęć: tytuł, nazwa pliku, liczba polubień i autorzy_id wskazujące autora - relacja 1..n).
Krok 3: Zrzut ekranu import.png
Kryteria:
R.1.1 Wykonano import tabel do bazy danych galeria czynność udokumentowano plikiem o nazwie import w formacie PNG
ok. 2 min
Polecenie z arkusza
Wykonaj zrzut ekranu po imporcie. Zrzut zapisz 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.
Print Screen, wklejenie do edytora grafiki i zapis jako import.png. Uwaga na formaty: import idzie do PNG, a zrzuty zapytań do JPEG.
Typowe błędy
Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).
Krok 4: Zapytanie 1: zdjęcia z co najmniej 100 polubieniami
Kryteria: ,
R.1.2 Zapisano plik kwerendy.txt zawierający co najmniej jedno zapytanie SQL, wynikające z treści zadania
R.1.3 Wykonano zapytanie 1 wybierające jedynie pola tytul i plik z tabeli zdjecia dla zdjęć z polubieniami większymi lub równymi 100. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT tytul, plik FROM zdjecia WHERE polubienia >= 100; oraz wynik działania udokumentowano zrzutem, na którym są widoczne dane: Slava Ukraini! kiev.jpg
ok. 1 min
Polecenie z arkusza
Zapytanie 1: wybierające jedynie pola tytul i plik z tabeli zdjecia dla zdjęć z polubieniami większymi lub równymi 100
SELECT tytul, plik - dwa pola,
FROM zdjecia,
WHERE polubienia >= 100 - „większymi lub równymi”, więc >=.
Wynik: jeden wiersz - Slava Ukraini! kiev.jpg, jak w kluczu. Z tego zapytania powstanie Skrypt 2 („Najbardziej lubiane”). Zapytania trafiają do kwerendy.txt, zrzut do kw1.jpg.
kwerendy.txtTekstnowy plik
-- Zapytanie 1SELECT tytul, plik FROM zdjecia WHERE polubienia >= 100;
Podgląd strony po tym kroku
Krok 5: Zapytanie 2: zdjęcia z autorami według nazwiska
Kryteria:
R.1.4 Wykonano zapytanie 2 wybierające jedynie pola plik, tytul, polubienia z tabeli zdjecia oraz odpowiadające im pola imie i nazwisko z tabeli autorzy posortowane rosnąco według nazwiska. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT plik, tytul, polubienia, imie, nazwisko FROM zdjecia JOIN autorzy ON autorzy_id = autorzy.id ORDER BY nazwisko; (możliwe również INNER JOIN lub bez JOIN i porównanie kluczy po WHERE, opcjonalnie ASC przy sortowaniu) oraz wynik działania udokumentowano zrzutem, na którym jest widocznych dokładnie 12 rekordów, jedynie pola plik, tytul, polubienia, imie, nazwisko, wyniki są posortowane wg. nazwiska
ok. 3 min
Polecenie z arkusza
Zapytanie 2: wybierające jedynie pola plik, tytul, polubienia z tabeli zdjecia oraz odpowiadające im pola imie i nazwisko z tabeli autorzy posortowane rosnąco według nazwiska. Należy posłużyć się relacją
SELECT plik, tytul, polubienia, imie, nazwisko - trzy pola zdjęcia i dwa autora,
FROM zdjecia JOIN autorzy - złączenie,
ON zdjecia.autorzy_id = autorzy.id - relacja z obrazu 1,
ORDER BY nazwisko - rosnąco (domyślnie, ASC można dopisać).
Wynik: 12 wierszy od zdjęć Jolanty Białej (Kijów, Praga, Wrocław) - w tej kolejności zdjęcia staną w galerii na obrazie 2. Zrzut: kw2.jpg. Z tego zapytania powstanie Skrypt 1.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT tytul, plik FROM zdjecia WHERE polubienia >= 100;-- Zapytanie 2SELECT plik, tytul, polubienia, imie, nazwisko FROM zdjecia JOIN autorzy ON zdjecia.autorzy_id = autorzy.id ORDER BY nazwisko;
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: liczba zdjęć dla każdego imienia
Kryteria:
R.1.5 Wykonano zapytanie 3 wybierające jedynie pole imie oraz liczące ile jest zdjęć dla tego imienia. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, COUNT(*) FROM zdjecia JOIN autorzy ON autorzy_id = autorzy.id GROUP BY imie; (lub dowolne pole zamiast *, możliwe również INNER JOIN lub bez JOIN i porównanie kluczy po WHERE) oraz wynik działania udokumentowano zrzutem, na którym są widoczne dane: Ewa 1; Ewelina 2; Jadwiga 4; Jan 2; Jolanta 3
ok. 2 min
Polecenie z arkusza
Zapytanie 3: wybierające jedynie pole imie oraz liczące ile jest zdjęć dla tego imienia. Należy posłużyć się relacją
SELECT imie, COUNT(*) - imię i liczba wierszy w grupie,
FROM zdjecia JOIN autorzy ON zdjecia.autorzy_id = autorzy.id - imię jest w tabeli autorów, a zdjęcia w drugiej, więc bez złączenia nie da się ich policzyć razem,
GROUP BY imie - jeden wiersz na każde imię.
Wynik: Ewa 1, Ewelina 2, Jadwiga 4, Jan 2, Jolanta 3 - autorzy bez zdjęć nie trafiają do wyniku, bo złączenie nie znajduje dla nich pary. Zrzut: kw3.jpg.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT tytul, plik FROM zdjecia WHERE polubienia >= 100;-- Zapytanie 2SELECT plik, tytul, polubienia, imie, nazwisko FROM zdjecia JOIN autorzy ON zdjecia.autorzy_id = autorzy.id ORDER BY nazwisko;-- Zapytanie 3SELECT imie, COUNT(*) FROM zdjecia JOIN autorzy ON zdjecia.autorzy_id = autorzy.id GROUP BY imie;
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: nowa kolumna rozmiarPliku
Kryteria:
R.1.6 Wykonano zapytanie 4 modyfikujące strukturę tabeli zdjecia. Dodana jest kolumna rozmiarPliku typu całkowitego. W pliku z kwerendami lub na zrzucie istnieje zapis np.: ALTER TABLE zdjecia ADD COLUMN rozmiarPliku INT; (słowo COLUMN jest opcjonalne, dowolny typ całkowity) oraz wynik działania udokumentowano zrzutem, na którym jest widoczny komunikat o poprawnym wykonaniu zapytania lub struktura tabeli z dodanym polem rozmiarPliku typu całkowitego
ok. 1 min
Polecenie z arkusza
Zapytanie 4: modyfikujące strukturę tabeli zdjecia. Dodana jest kolumna rozmiarPliku typu całkowitego
ALTER TABLE zdjecia - zmiana struktury tabeli, nie danych,
ADD COLUMN rozmiarPliku INT - nowa kolumna typu całkowitego; w istniejących wierszach dostaje wartość NULL.
Zapytanie nie zwraca wierszy - na zrzucie kw4.jpg widać komunikat o poprawnym wykonaniu albo strukturę tabeli z nowym polem (int(11)). Skrypty strony wybierają konkretne kolumny, więc nowe pole im nie przeszkadza.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT tytul, plik FROM zdjecia WHERE polubienia >= 100;-- Zapytanie 2SELECT plik, tytul, polubienia, imie, nazwisko FROM zdjecia JOIN autorzy ON zdjecia.autorzy_id = autorzy.id ORDER BY nazwisko;-- Zapytanie 3SELECT imie, COUNT(*) FROM zdjecia JOIN autorzy ON zdjecia.autorzy_id = autorzy.id GROUP BY imie;-- Zapytanie 4ALTER TABLE zdjecia ADD COLUMN rozmiarPliku INT;
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 8-20 · po tym etapie masz 14 z 37 kryteriów (pkt)
Krok 8: woodpecker.jpg: dokładnie 520 × 346 px
Kryteria:
R.2.1 Grafikę woodpecker.jpg przeskalowano do dokładnych wymiarów: szerokość 520 px i wysokość 346 px
ok. 2 min
Polecenie z arkusza
Plik woodpecker.jpg, wypakowany z archiwum, należy przeskalować do dokładnych wymiarów szerokość 520 px i wysokość 346 px.
Wszystkie zdjęcia z archiwum mają 520 × 346 pikseli - poza woodpecker.jpg (640 × 428). W GIMP-ie: Obraz → Skaluj obraz, rozłączony łańcuch między szerokością a wysokością i wpisane obie wartości: 520 i 346. Przy zamkniętym łańcuchu po wpisaniu szerokości 520 program sam wyliczy wysokość 348 (640 i 428 mają inne proporcje niż 520 i 346), a arkusz wymaga dokładnych wymiarów. Różnica dwóch pikseli nie zniekształca widocznie zdjęcia. Eksport pod tą samą nazwą: Plik → Nadpisz woodpecker.jpg.
Typowe błędy
Zdjęcie 520 × 348 (z zamkniętym łańcuchem) nie spełnia warunku „dokładnych wymiarów”.
Podgląd strony po tym kroku
Krok 9: Plik galeria.php w HTML5
ok. 1 min
Polecenie z arkusza
Składa się ze strony o nazwie galeria.php zapisanej w języku HTML5
Deklaracja <!DOCTYPE html>, sekcje head i body. Rozszerzenie .php, bo dojdą skrypty; strona otwiera się przez http://localhost/....
R.2.2 Witrynę internetową zapisano w pliku galeria.php oraz zapisano jawnie standard kodowania polskich znaków i deklarację HTML5 <!DOCTYPE HTML> i zadeklarowano język witryny polski np.<HTML lang="pl">. Strona zawiera sekcje head i body
ok. 1 min
Polecenie z arkusza
Jawnie zastosowany właściwy standard kodowania polskich znaków
<meta charset="UTF-8"> jako pierwszy element <head>. Ten krok zamyka kryterium R.2.2: nazwa pliku, deklaracja HTML5, język i kodowanie.
R.3.3 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl.css , formatowanie CSS pochodzi jedynie z tego arkusza Uwaga: kryterium to nie jest spełnione również, gdy zdający źle przypisał co najmniej jeden selektor do bloku (np. kropka zamiast #)
ok. 1 min
Polecenie z arkusza
Arkusz stylów w pliku o nazwie styl.css prawidłowo połączony z kodem strony
Nazwa pliku: styl.css (nie style.css). Klucz przypomina, że R.3.3 przepada także wtedy, gdy któryś selektor jest źle zapisany, np. kropka zamiast # przy identyfikatorze.
R.2.4 Układ strony zdefiniowano dzieląc ją na bloki: baner, lewy, środkowy, prawy oraz stopkę. Zastosowano semantyczne znaczniki sekcji HTML5 zgodnie z ich znaczeniem, w tym do części nagłówkowej - header, stopki - footer, dopuszcza się zagnieżdżenie bloków div w znacznikach semantycznych
ok. 2 min
Polecenie z arkusza
Podział strony na bloki: baner, poniżej trzy bloki: lewy, środkowy i prawy, na dole blok stopki. Podział zrealizowany wyłącznie za pomocą semantycznych znaczników sekcji języka HTML5 tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z obrazem 2
Baner to header, stopka footer (klucz wymaga ich wprost - R.2.4). Galeria jest główną treścią strony, więc środkowy blok to main. Bloki po bokach zawierają treść dodatkową (tematy, najbardziej lubiane zdjęcie) - oba to aside, rozróżnione identyfikatorami left i right. Kolejność w kodzie jest taka jak na obrazie 2, od lewej do prawej.
Krok 19: Napis w znaczniku tekstu o dużym znaczeniu
Kryteria:
R.2.9 W bloku prawym umieszczono napis o treści „Zobacz wszystkie nasze zdjęcia” zapisany w znaczniku semantycznym pisanym czcionką pogrubioną i oznaczającym tekst o dużym znaczeniu - znacznik <strong>
ok. 1 min
Polecenie z arkusza
Napis o treści „Zobacz wszystkie nasze zdjęcia” zapisany w znaczniku semantycznym pisanym czcionką pogrubioną i oznaczającym tekst o dużym znaczeniu
Tekst o dużym znaczeniu to <strong> (domyślnie pogrubiony; <b> też pogrubia, ale nie niesie znaczenia). Celowo bez paragrafu <p> - arkusz go nie wymaga, a za chwilę paragrafy w galerii dostaną styl ukrywający, który nie powinien dotknąć tego napisu.
R.2.5 W banerze zapisano nagłówek h1: "Zdjęcia" , w bloku lewym h2: "Tematy zdjęć" , w bloku prawym h2: "Najbardziej lubiane" , w stopce h5 z numerem zdającego
ok. 1 min
Polecenie z arkusza
Zawartość stopki: nagłówek piątego stopnia o treści „Stronę wykonał: ”, dalej wstawiony numer zdającego
Nagłówek <h5>. Na egzaminie w miejscu imienia i nazwiska wpisuje się numer zdającego, czyli PESEL; w tym rozwiązaniu stoi tam „Bartosz Bryniarski”. Strona ma już wszystkie nagłówki z klucza (R.2.5).
Domyślne formatowanie wszystkich selektorów: krój czcionki Helvetica
Selektor uniwersalny *. Na Windows Helvetica zwykle nie jest zainstalowana - przeglądarka użyje wtedy kroju domyślnego (na obrazie 2 to Arial); arkusz nie prosi o krój zapasowy.
styl.cssCSSnowy plik
* {font-family: Helvetica;}
Podgląd strony po tym kroku (galeria.php)
Krok 22: Baner i stopka: kolory, odstęp, wyśrodkowanie
ok. 1 min
Polecenie z arkusza
Wspólne dla banera i stopki: kolor tła Sienna, biały kolor czcionki, marginesy wewnętrzne 10 px, wyrównanie tekstu do środka
Dwa selektory po przecinku - jedna reguła dla obu bloków.
Krok 24: Blok środkowy: wymiary i paski przewijania
Kryteria: ,
R.4.3 Ustawiono wysokość bloków lewego, środkowego i prawego na 700px
R.4.5 Ustawiono wyrównanie tekstu do środka dla banera i stopki oraz zawsze widoczne paski przewijania (overflow: scroll;) dla bloku środkowego
ok. 2 min
Polecenie z arkusza
Dla bloku środkowego: szerokość 70%, wysokość 700 px, zawsze widoczne paski przewijania
„Zawsze widoczne” to overflow: scroll - pasek jest rysowany od początku, a dwanaście zdjęć i tak nie zmieści się w 700 px, więc galerię przewija się wewnątrz bloku. Ustawione są już wysokości trzech bloków (R.4.3), a wyśrodkowanie banera i stopki razem z paskami tego bloku to R.4.5.
R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z obrazem 2 w arkuszu. Nie należy brać pod uwagę bloków generowanych skryptem. (prawidłowo zastosowano właściwości CSS decydujące o układzie strony np. float i clear albo display flex albo grid)
ok. 2 min
Polecenie z arkusza
Podział strony na bloki: baner, poniżej trzy bloki: lewy, środkowy i prawy, na dole blok stopki. Podział zrealizowany wyłącznie za pomocą semantycznych znaczników sekcji języka HTML5 tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z obrazem 2
Trzy bloki pod banerem float: left - stają obok siebie w kolejności z kodu (15% + 70% + 15% = cała szerokość). Stopka z clear: both zaczyna się pod nimi.
R.4.4 Ustawiono szerokość bloku lewego i prawego 15%, środkowego 70% (width lub grid- template-columns lub flex), selektora img 100%
ok. 1 min
Polecenie z arkusza
Dla selektora obrazu: szerokość 100%
Obraz zajmuje całą szerokość swojego rodzica: w galerii - bloku zdjęcia, w prawym bloku - całego bloku. Zgodnie z uwagą arkusza selektor to sam znacznik img. Komplet szerokości z klucza (R.4.4).
Krok 27: Blok zdjęcia: obok siebie, szerokość, marginesy, pozycja względna
Kryteria:
R.4.7 Ustawiono dla bloku generowanego skryptem 1: bloki ustawione obok siebie, szerokość 46%, marginesy zewnętrzne (margin) 2% (np. dla klasy, id jest błędem )
ok. 2 min
Polecenie z arkusza
Dla bloku generowanego skryptem 1 i zawierającego zdjęcie i opis: bloki ustawione obok siebie (opływanie), szerokość 46%, marginesy zewnętrzne 2%, pozycjonowanie względne
Bloki zdjęć wypisze Skrypt 1 z klasą photo (klucz: klasa, identyfikator byłby błędem - bloków jest dwanaście). „Opływanie” to float: left. 46% + 2% marginesu z każdej strony = 50%, więc w rzędzie mieszczą się dwa zdjęcia. position: relative nie przesuwa bloku, ale czyni go punktem odniesienia dla elementów pozycjonowanych absolute w środku - opis zdjęcia ułoży się na zdjęciu, a nie na całej stronie. Efekt będzie widać, gdy Skrypt 1 wypisze bloki.
Krok 28: Opis zdjęcia: niewidoczny i pozycjonowany na zdjęciu
Kryteria:
R.4.9 Ustawiono pełną przezroczystość dla nagłówka trzeciego stopnia, paragrafu i odnośnika (opacity: 0;)
ok. 2 min
Polecenie z arkusza
Wspólne dla nagłówka trzeciego stopnia, paragrafu, odnośnika: pełna przezroczystość (0), pozycjonowanie pozwalające przesuwać element względem rodzica
opacity: 0 - element jest w pełni przezroczysty (nadal istnieje i reaguje na kliknięcie, tylko go nie widać). Przesuwanie „względem rodzica” to position: absolute z tabeli 2 arkusza - liczy się od najbliższego przodka z pozycją względną, czyli od bloku photo. Selektory zaczynają się od .photo, żeby styl dotyczył tylko opisu zdjęć: samo p albo a ukryłoby też inne paragrafy i odnośniki, które pojawiłyby się na stronie.
R.4.8 Ustawiono cechy pozycjonowania (position): relative dla bloku generowanego skryptem 1, absolute dla nagłówka trzeciego stopnia, paragrafu i odnośnika oraz odległości od górnej krawędzi (top) 5% dla nagłówka trzeciego stopnia, 30% dla paragrafu, 70% dla odnośnika oraz od lewej krawędzi (left) 70% dla odnośnika (kryterium należy uznać za spełnione, gdy poprawnie zdefiniowano formatowanie dla co najmniej 4 z 6 elementów)
R.4.2 Ustawiono kolor tła Sienna i biały kolor czcionki dla banera i stopki, kolor tła: Navaj oWhite dla bloku lewego i prawego oraz kolor tła Sienna dla odnośnika
R.4.6 Ustawiono marginesy wewnętrzne (padding) 10px dla banera i stopki, 15px dla odnośnika
ok. 2 min
Polecenie z arkusza
Dodatkowo dla odnośnika: odległość od górnej krawędzi rodzica 70%, od lewej krawędzi 70%, kolor tła Sienna, marginesy wewnętrzne 15 px
top i left stawiają odnośnik w prawym dolnym rogu zdjęcia, a tło Sienna z odstępem 15 px robi z niego przycisk (obraz 3). Pozycjonowanie wszystkich elementów opisu jest komplet (R.4.8), tak samo kolory tła (R.4.2) i marginesy wewnętrzne (R.4.6).
Krok 32: Blok pod kursorem: zdjęcie blednie, opis się pojawia
Kryteria:
R.4.10 W momencie, gdy kursor myszy znajdzie się na bloku generowanym skryptem 1: przezroczystość dla zdjęcia w tym bloku zmienia się na 0.3, przezroczystość dla nagłówka trzeciego stopnia, paragrafu i odnośnika zmienia się na 1, dla zdjęcia zdefiniowano płynne przejście transition: 0.5s ease
ok. 3 min
Polecenie z arkusza
W momencie, gdy kursor myszy znajdzie się na bloku generowanym skryptem 1: Zdjęcia z bloku środkowego przyjmują wartość przezroczystości 0.3 i jest ona zmieniana płynnie przez 0.5 sekundy efektem ease. Nagłówka trzeciego stopnia: brak przezroczystości (1). Paragrafu: brak przezroczystości. Odnośnika: brak przezroczystości
Selektor .photo:hover img czyta się „obraz w bloku zdjęcia, nad którym stoi kursor” - pseudoklasa dotyczy bloku, a zmiana jego potomków. Zdjęcie przechodzi do przezroczystości 0.3, a tytuł, autor i odnośnik do 1 (pełna widoczność). transition: 0.5s ease stoi w zwykłej regule obrazu, więc zdjęcie blednie przez pół sekundy i tak samo płynnie wraca po zjechaniu kursora; ease to krzywa „wolno - szybko - wolno” (składnię transition podaje tabela 3 arkusza).
Kroki 33-42 · po tym etapie masz 37 z 37 kryteriów (pkt)
Krok 33: Połączenie w Skrypcie 1, zamknięcie w Skrypcie 2
Kryteria:
R.5.1 Skrypt zawiera instrukcje połączenia z serwerem bazy danych i wyboru bazy galeria
ok. 2 min
Polecenie z arkusza
Skrypty łączą się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie galeria
Skrypt 1 wypełnia blok środkowy, więc stoi wewnątrz <main>; jest pierwszy na stronie i otwiera połączenie (mysqli_connect łączy się z serwerem i wybiera bazę, uchwyt w $connection). Skrypt 2 stoi w prawym bloku pod nagłówkiem - na razie tylko zamyka połączenie, a swoje instrukcje dostanie nad tą linią. Od tego kroku podgląd to wynik prawdziwego uruchomienia strony.
Krok 35: Skrypt 1: osobny blok dla każdego wiersza
Kryteria:
R.5.4 Skrypt 1 tworzy element blokowy dla każdego zwróconego z bazy wiersza
ok. 2 min
Polecenie z arkusza
Każdy zwrócony zapytaniem wiersz jest wyświetlany w osobnym bloku (obraz 3)
Pętla while z mysqli_fetch_row przechodzi przez 12 wierszy wyniku i dla każdego wypisuje <div class="photo"> - na razie pusty. Cudzysłowy w HTML-u wewnątrz napisu PHP poprzedza ukośnik \". Numery kolumn w $row liczą się od pól zapytania: $row[0] - plik, $row[1] - tytuł, $row[2] - polubienia, $row[3] - imię, $row[4] - nazwisko.
Krok 36: Skrypt 1: zdjęcie z tekstem alternatywnym
Kryteria: ,
R.5.5 W każdym bloku wyświetlono zdjęcie, którego źródłem jest pole <plik> z bazy
R.2.7 W bloku środkowym umieszczono przynajmniej jeden obraz z tekstem alternatywnym "zdjęcie" (wygenerowany skryptem lub w HTML)
ok. 2 min
Polecenie z arkusza
Każdy blok zawiera: Obraz, którego źródło zostało zwrócone zapytaniem, z tekstem alternatywnym „zdjęcie”
Źródło to nazwa pliku z pierwszej kolumny, a tekst alternatywny - stałe słowo „zdjęcie”, jak w arkuszu. Podgląd wygląda już jak obraz 2: zdjęcia po dwa w rzędzie, od Kijowa, Pragi i Wrocławia, z paskiem przewijania bloku środkowego.
Krok 38: Skrypt 1: autor i „Wiele osób polubiło” przy ponad 40 polubieniach
ok. 2 min
Polecenie z arkusza
W przypadku, gdy zwrócona wartość polubień jest większa niż 40: paragraf o treści: „Autor: <imię><nazwisko>. Wiele osób polubiło ten obraz”, łamanie linii po kropce.
Warunek na trzeciej kolumnie: $row[2] > 40 - „większa niż”, więc „Urocze jeziorko” z dokładnie 40 polubieniami się nie łapie. Łamanie linii po kropce to <br> w środku paragrafu (obraz 3: „Autor: Jadwiga Kowalska.” i pod spodem „Wiele osób polubiło ten obraz”).
galeria.phpPHPzmienione: 3 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Galeria</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Zdjęcia</h1> </header> <asideid="left"> <h2>Tematy zdjęć</h2> <ol> <li>Zwierzęta</li> <li>Krajobrazy</li> <li>Miasta</li> <li>Przyroda</li> <li>Samochody</li> </ol> </aside> <main><?php$connection = mysqli_connect("localhost", "root", "", "galeria");$query = "SELECT plik, tytul, polubienia, imie, nazwisko FROM zdjecia JOIN autorzy ON zdjecia.autorzy_id = autorzy.id ORDER BY nazwisko;";$result = mysqli_query($connection, $query);while ($row = mysqli_fetch_row($result)) {echo"<div class=\"photo\">";echo"<img src=\"$row[0]\" alt=\"zdjęcie\">";echo"<h3>$row[1]</h3>";if ($row[2] > 40) {echo"<p>Autor: $row[3]$row[4].<br>Wiele osób polubiło ten obraz</p>"; }echo"</div>"; }?> </main> <asideid="right"> <h2>Najbardziej lubiane</h2><?php mysqli_close($connection);?> <strong>Zobacz wszystkie nasze zdjęcia</strong> </aside> <footer> <h5>Stronę wykonał: Bartosz Bryniarski</h5> </footer></body></html>
Podgląd strony po tym kroku (galeria.php)
Krok 39: Skrypt 1: sam autor w przeciwnym wypadku
Kryteria:
R.5.7 Gdy zwrócona zapytaniem wartość polubień jest większa niż 40 wyświetlony jest tekst: "Wiele osób polubiło ten obraz" , w przeciwnym wypadku tekst nie jest wyświetlony
ok. 1 min
Polecenie z arkusza
W przeciwnym wypadku paragraf o treści: „Autor: <imię><nazwisko>”, gdzie pola w nawiasach <> zostały pobrane z bazy danych
Gałąź else - paragraf bez kropki i bez drugiej linii. Sprawdzone na bazie z arkusza: dłuższy napis dostaje 5 zdjęć (Kijów, Praga, Wrocław, motyl i dzięcioł), krótszy - pozostałe 7.
Krok 40: Skrypt 1: odnośnik „Pobierz” z atrybutem download
Kryteria: ,
R.3.2 Zapisano na stronie przynajmniej jeden odnośnik o treści „Pobierz" , wskazujący na dowolny plik graficzny. Po kliknięciu na odnośnik, zdjęcie jest pobierane - atrybut download (wygenerowana skryptem lub w HTML)
R.5.6 W każdym bloku wyświetlono tytuł, imię i nazwisko oraz odnośnik prowadzący do grafiki, której nazwa pliku jest zwrócona z bazy
ok. 2 min
Polecenie z arkusza
Odnośnik o treści „Pobierz” wskazujący na nazwę pliku zwróconą zapytaniem. Po kliknięciu na odnośnik, zdjęcie jest pobierane
Zwykły odnośnik do pliku JPG otworzyłby zdjęcie w przeglądarce. Atrybut download każe je zapisać na dysku (R.3.2). Działa dla plików z tego samego serwera - a zdjęcia leżą obok strony. Każdy blok ma teraz zdjęcie, tytuł, autora i odnośnik do pliku (R.5.6).
Krok 42: Skrypt 2: zdjęcie z tytułem jako tekstem alternatywnym
Kryteria: , , ,
R.5.8 Skrypt 2 wyświetla obraz, którego źródło zwrócone zapytaniem 1, wraz z tekstem alternatywnym pobranym z pola tytuł
R.2.8 W bloku prawym umieszczono obraz z tekstem alternatywnym (wygenerowany skryptem lub w HTML)
R.5.2 Ostatnią operacją na bazie jest jej zamknięcie
R.5.9 Zastosowano znaczące nazewnictwo dla wszystkich zmiennych lub funkcji w języku polskim lub angielskim. Nazwy odzwierciedlają cel zastosowania
ok. 2 min
Polecenie z arkusza
Wyświetla obraz, którego źródło zostało zwrócone zapytaniem, wraz z tekstem alternatywnym pobranym z pola tytul
Wiersz jest jeden, więc wystarczy jedno mysqli_fetch_row bez pętli. Kolejność kolumn zapytania 1 jest odwrotna niż w galerii: $row[0] - tytuł (do alt), $row[1] - plik (do src). Obraz ma szerokość całego prawego bloku (img 100%), a pod nim stoi pogrubiony napis - jak na obrazie 2 (R.5.8, R.2.8).
To ostatni krok skryptów: połączenie zamyka mysqli_close na końcu Skryptu 2 (R.5.2), a wszystkie zmienne mają nazwy mówiące, co przechowują: $connection, $query, $result, $row (R.5.9).
Kroki 43-45 · po tym etapie masz 37 z 37 kryteriów (pkt)
Krok 43: Skrypt 2 odporny na brak zdjęcia i cudzysłów w tytule
ok. 3 min
Polecenie z arkusza
Wyświetla obraz, którego źródło zostało zwrócone zapytaniem, wraz z tekstem alternatywnym pobranym z pola tytul
Wersja egzaminacyjna sprawdzona na dwóch zmianach w bazie. Gdy żadne zdjęcie nie ma stu polubień (Kijów z 99), mysqli_fetch_row zwraca null i PHP wypisuje ostrzeżenia „Trying to access array offset on value of type null” prosto na stronę. Gdy tytuł zawiera cudzysłów (Kijów "nocą"), atrybut alt urywa się na drugim cudzysłowie i znacznik jest uszkodzony. Poprawki: warunek if ($favourite) wypisuje obraz tylko wtedy, gdy wiersz istnieje, a htmlspecialchars zamienia cudzysłów na ". Przy okazji ORDER BY polubienia DESC LIMIT 1 daje jedno, naprawdę najbardziej lubiane zdjęcie, nawet gdy stu polubień dobije kilka zdjęć, a mysqli_fetch_assoc pozwala pisać $favourite["plik"] zamiast pamiętać numer kolumny. Stare linie zostają w komentarzu. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
galeria.phpPHPzmienione: 8 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Galeria</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Zdjęcia</h1> </header> <asideid="left"> <h2>Tematy zdjęć</h2> <ol> <li>Zwierzęta</li> <li>Krajobrazy</li> <li>Miasta</li> <li>Przyroda</li> <li>Samochody</li> </ol> </aside> <main><?php$connection = mysqli_connect("localhost", "root", "", "galeria");$query = "SELECT plik, tytul, polubienia, imie, nazwisko FROM zdjecia JOIN autorzy ON zdjecia.autorzy_id = autorzy.id ORDER BY nazwisko;";$result = mysqli_query($connection, $query);while ($row = mysqli_fetch_row($result)) {echo"<div class=\"photo\">";echo"<img src=\"$row[0]\" alt=\"zdjęcie\">";echo"<h3>$row[1]</h3>";if ($row[2] > 40) {echo"<p>Autor: $row[3]$row[4].<br>Wiele osób polubiło ten obraz</p>"; } else {echo"<p>Autor: $row[3]$row[4]</p>"; }echo"<a href=\"$row[0]\" download>Pobierz</a>";echo"</div>"; }?> </main> <asideid="right"> <h2>Najbardziej lubiane</h2><?php$query = "SELECT tytul, plik FROM zdjecia WHERE polubienia >= 100 ORDER BY polubienia DESC LIMIT 1;";$result = mysqli_query($connection, $query);$favourite = mysqli_fetch_assoc($result);if ($favourite) {echo"<img src=\"" . htmlspecialchars($favourite["plik"]) . "\" alt=\"" . htmlspecialchars($favourite["tytul"]) . "\">"; }// $query = "SELECT tytul, plik FROM zdjecia WHERE polubienia >= 100;";// $row = mysqli_fetch_row($result);// echo "<img src=\"$row[1]\" alt=\"$row[0]\">"; mysqli_close($connection);?> <strong>Zobacz wszystkie nasze zdjęcia</strong> </aside> <footer> <h5>Stronę wykonał: Bartosz Bryniarski</h5> </footer></body></html>
Krok 44: Skrypt 1: kolumny po nazwach i htmlspecialchars
ok. 3 min
Polecenie z arkusza
Każdy zwrócony zapytaniem wiersz jest wyświetlany w osobnym bloku (obraz 3)
Pięć kolumn po numerach łatwo pomylić - w Skrypcie 2 kolejność była odwrotna. mysqli_fetch_assoc oddaje wiersz z kluczami takimi jak nazwy kolumn ($photo["polubienia"] zamiast $row[2]). Nazwa pliku i autor są policzone raz, do zmiennych, a tytuł, plik i autor przechodzą przez htmlspecialchars - tak jak w Skrypcie 2, cudzysłów albo < w danych nie rozbije znaczników. Strona wygląda tak samo jak wcześniej. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
galeria.phpPHPzmienione: 10 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Galeria</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Zdjęcia</h1> </header> <asideid="left"> <h2>Tematy zdjęć</h2> <ol> <li>Zwierzęta</li> <li>Krajobrazy</li> <li>Miasta</li> <li>Przyroda</li> <li>Samochody</li> </ol> </aside> <main><?php$connection = mysqli_connect("localhost", "root", "", "galeria");$query = "SELECT plik, tytul, polubienia, imie, nazwisko FROM zdjecia JOIN autorzy ON zdjecia.autorzy_id = autorzy.id ORDER BY nazwisko;";$result = mysqli_query($connection, $query);while ($photo = mysqli_fetch_assoc($result)) {$file = htmlspecialchars($photo["plik"]);$author = htmlspecialchars($photo["imie"] . "" . $photo["nazwisko"]);echo"<div class=\"photo\">";echo"<img src=\"$file\" alt=\"zdjęcie\">";echo"<h3>" . htmlspecialchars($photo["tytul"]) . "</h3>";if ($photo["polubienia"] > 40) {echo"<p>Autor: $author.<br>Wiele osób polubiło ten obraz</p>"; } else {echo"<p>Autor: $author</p>"; }echo"<a href=\"$file\" download>Pobierz</a>";echo"</div>"; }// wersja z egzaminu: while ($row = mysqli_fetch_row($result)) - kolumny po numerach $row[0] ... $row[4]?> </main> <asideid="right"> <h2>Najbardziej lubiane</h2><?php$query = "SELECT tytul, plik FROM zdjecia WHERE polubienia >= 100 ORDER BY polubienia DESC LIMIT 1;";$result = mysqli_query($connection, $query);$favourite = mysqli_fetch_assoc($result);if ($favourite) {echo"<img src=\"" . htmlspecialchars($favourite["plik"]) . "\" alt=\"" . htmlspecialchars($favourite["tytul"]) . "\">"; }// $query = "SELECT tytul, plik FROM zdjecia WHERE polubienia >= 100;";// $row = mysqli_fetch_row($result);// echo "<img src=\"$row[1]\" alt=\"$row[0]\">"; mysqli_close($connection);?> <strong>Zobacz wszystkie nasze zdjęcia</strong> </aside> <footer> <h5>Stronę wykonał: Bartosz Bryniarski</h5> </footer></body></html>
Krok 45: Opis widoczny także z klawiatury i na ekranie dotykowym
ok. 2 min
Polecenie z arkusza
W momencie, gdy kursor myszy znajdzie się na bloku generowanym skryptem 1: Zdjęcia z bloku środkowego przyjmują wartość przezroczystości 0.3 i jest ona zmieniana płynnie przez 0.5 sekundy efektem ease. Nagłówka trzeciego stopnia: brak przezroczystości (1). Paragrafu: brak przezroczystości. Odnośnika: brak przezroczystości
Opis zdjęcia pokazuje się tylko pod kursorem myszy. Kto przechodzi po stronie klawiszem Tab, trafia na niewidoczny odnośnik „Pobierz” - nie widzi ani jego, ani tytułu. Pseudoklasa :focus-within jest prawdziwa dla bloku, w którego środku jest element z fokusem: po dojściu tabulatorem do „Pobierz” zdjęcie blednie, a opis się pojawia - tak samo jak po najechaniu myszą. Na telefonie pierwsze dotknięcie odnośnika działa podobnie. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
Krok 46 · po tym etapie masz 37 z 37 kryteriów (pkt)
Krok 46: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
Po zakończeniu pracy utwórz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowana była poprawność działania witryny. Umieść go w folderze z numerem zdającego. Nagraj płytę z rezultatami pracy.
W przeglądarka.txt wystarczy nazwa przeglądarki, w której była sprawdzana strona.
W folderze z numerem zdającego: galeria.php, import.png, kw1.jpg - kw4.jpg, kwerendy.txt, przeglądarka.txt, styl.css, wszystkie zdjęcia z archiwum (w tym przeskalowany woodpecker.jpg) i rozpakowany baza.sql. Po nagraniu płyty trzeba sprawdzić jej odczyt i opisać ją numerem zdającego.
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
To jedno z możliwych rozwiązań. Egzaminator ocenia spełnienie kryteriów z klucza odpowiedzi, a nie zgodność z tym kodem - inna, poprawna droga też daje punkty.
Autor rozwiązania: Bartosz Bryniarski. Licencja CC BY-NC 4.0 - kopiowanie i przeróbki do celów niekomercyjnych, z podaniem autora i źródła (link do tej strony) (zasady wykorzystania). Treść arkusza i klucza oceniania pochodzi z CKE.