INF.03-11-24.06-SGCzerwiec 2024 · 41 kroków · ok. 81 min · 40 kryteriów z klucza
Rozwiązanie krok po kroku: Witryna hodowli świnek morskich (Nowoczesny kod (grid, PDO))
To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza hodowla z czterema zapytaniami, wykadrowane zdjęcie i trzy strony (peruwianka.php, american.php, crested.php) z menu, listą ras, danymi miotu i świnkami z tego miotu - i tak samo spełnia każde kryterium klucza. Inna jest droga:
siatka CSS na całej stronie: grid-template-areas stawia menu i blok główny po lewej, blok prawy obok obu, a szerokości 80% i 20% stoją w grid-template-columns (klucz R.4.5 przyjmuje je wprost). Kod HTML ma kolejność treści, bez float bloków i bez clear,
PHP na PDO: wszystkie dane strona pobiera na górze pliku, przed HTML-em - połączenie, trzy zapytania i zamknięcie połączenia w jednym bloku try, a w HTML-u zostają tylko pętle i wypisywanie,
zapytania przygotowane z parametrem :breed i identyfikator rasy w jednej zmiennej - kopie strony różnią się jedną linią i obrazem, nie czterema miejscami,
bezpieczne wypisywanie (htmlspecialchars w funkcji e()) i komunikaty dla rasy bez miotu, bez świnek i dla awarii bazy - zamiast pustych nagłówków albo błędu PHP.
Na końcu krótkie porównanie z wersją podstawową (zakładka obok). Baza i zdjęcia pochodzą z prawdziwego archiwum pliki11, a podgląd od kroków z PHP to wynik prawdziwego uruchomienia kodu w PHP 8.2 na bazie z arkusza (także dla rasy bez świnek i dla wyłączonej bazy).
Jak liczą się punkty. Klucz ma 40 kryteriów (R.1.1 - R.5.10), każde za 1 punkt. Próg zdania to 75%, czyli 30 punktów. Przy każdym kroku jest napisane, które kryteria spełnia.
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 40 kryteriów (pkt)
Krok 1: Baza danych hodowla
ok. 2 min
Polecenie z arkusza
Utwórz bazę danych o nazwie hodowla, z zestawem polskich znaków (np. utf8_unicode_ci)
Archiwum pliki11.zip rozpakuj hasłem @Swinki-MorSkie! (małpa na początku, wielkie S w środku, wykrzyknik na końcu) do folderu z numerem zdającego. W phpMyAdmin Nowa → hodowla, porównywanie utf8_unicode_ci, albo zapytaniem:
CREATE DATABASE hodowla CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Typowe błędy
Skrypty łączą się z bazą po nazwie - literówka w nazwie bazy zabiera punkty za część PHP (R.5.1).
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 hodowla, Import → baza.sql. Dwie tabele z obrazu 1: rasy (13 ras) i swinki (data urodzenia, miot, opis, imię, cena i klucz obcy rasy_id).
Krok 3: Zrzut ekranu import.png
Kryteria:
R.1.1 Wykonano import tabel do bazy danych hodowla 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.
Cały ekran z paskiem zadań, w PNG. Zrzuty zapytań idą do JPEG i tym razem muszą pokazywać także treść wykonanego zapytania (phpMyAdmin wyświetla ją nad wynikiem).
Typowe błędy
Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).
Krok 4: Zapytanie 1: świnki urodzone w lipcu
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 imie i miot z tabeli swinki dla świnek morskich urodzonych w lipcu. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, miot FROM swinki WHERE data_ur LIKE "%-07-%"; (różne formy wyrażenia regularnego) oraz wynik działania udokumentowano zrzutem, na którym są widoczne dokładnie 3 wiersze z danymi: Ed C4, Tikka C4, Frania C4
ok. 3 min
Polecenie z arkusza
Zapytanie 1: wybierające jedynie pola imie i miot z tabeli swinki dla świnek morskich urodzonych w lipcu
MONTH(data_ur) = 7 - funkcja daty wyciąga numer miesiąca, więc warunek działa na dacie, a nie na jej zapisie tekstowym (LIKE "%-07-%" z klucza też zadziała, ale zależy od formatu RRRR-MM-DD). Wynik: 3 wiersze - Ed, Tikka, Frania, wszystkie z miotu C4. Zapytania zapisz w kwerendy.txt, zrzut z treścią zapytania jako kw1.jpg.
R.1.4 Wykonano zapytanie 2 wybierające niepowtarzające się wiersze z datą urodzenia i miotem z tabeli swinki oraz odpowiadającą im nazwą rasy z tabeli rasy dla id rasy równego 1. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT DISTINCT data_ur, miot, rasa FROM swinki JOIN rasy ON rasy_id = rasy.id WHERE rasy_id=1; (lub rasy.id=1; możliwe również INNER JOIN lub bez JOIN i porównanie kluczy po WHERE) oraz wynik działania udokumentowano zrzutem, na którym jest widoczny dokładnie 1 wiersz: 2022-06-02 I5 peruwianka
ok. 3 min
Polecenie z arkusza
Zapytanie 2: wybierające niepowtarzające się wiersze z datą urodzenia i miotem z tabeli swinki oraz odpowiadającą im nazwą rasy z tabeli rasy dla id rasy równego 1. Należy posłużyć się relacją
DISTINCT zostawia jeden wiersz z każdego powtórzenia - cztery świnki z jednego miotu dają jeden wiersz. Aliasy s (swinki) i r (rasy), ON r.id = s.rasy_id - para kluczy relacji. Wynik: 1 wiersz - 2022-06-02, I5, peruwianka. Zrzut: kw2.jpg.
Typowe błędy
Bez DISTINCT zrzut pokazuje 4 wiersze - klucz wymaga dokładnie jednego.
kwerendy.txtTekstzmienione: 6 linii
-- Zapytanie 1SELECT imie, miotFROM swinkiWHERE MONTH(data_ur) = 7;-- Zapytanie 2SELECT DISTINCT s.data_ur, s.miot, r.rasaFROM swinki AS sJOIN rasy AS r ON r.id = s.rasy_idWHERE r.id = 1;
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: świnki rasy peruwianka
Kryteria:
R.1.5 Wykonano zapytanie 3 wybierające jedynie imię, cenę i opis świnek morskich, których id rasy jest równe 1. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, cena, opis FROM swinki WHERE rasy_id = 1; (lub z zastosowaniem relacji) oraz wynik działania udokumentowano zrzutem, na którym są widoczne dokładnie 4 wiersze, jedynie pola imie, cena, opis dla imion: Cindy, Wendy, Mała, Lola
ok. 2 min
Polecenie z arkusza
Zapytanie 3: wybierające jedynie imię, cenę i opis świnek morskich, których id rasy jest równe 1
Trzy pola i warunek na kluczu obcym rasy_id - złączenie nie jest potrzebne. Wynik: 4 wiersze - Cindy, Wendy, Mała, Lola. Zrzut: kw3.jpg.
kwerendy.txtTekstzmienione: 5 linii
-- Zapytanie 1SELECT imie, miotFROM swinkiWHERE MONTH(data_ur) = 7;-- Zapytanie 2SELECT DISTINCT s.data_ur, s.miot, r.rasaFROM swinki AS sJOIN rasy AS r ON r.id = s.rasy_idWHERE r.id = 1;-- Zapytanie 3SELECT imie, cena, opisFROM swinkiWHERE rasy_id = 1;
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: wszystkie rasy
Kryteria:
R.1.6 Wykonano zapytanie 4 wybierające jedynie rasę z tabeli rasy . W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT rasa FROM rasy; oraz wynik działania udokumentowano zrzutem, na którym jest widocznych dokładnie 13 wierszy, jedynie nazwy ras
ok. 1 min
Polecenie z arkusza
Zapytanie 4: wybierające jedynie rasę z tabeli rasy
Jedno pole, 13 wierszy. ORDER BY id (dodatek) ustala kolejność listy na stronie: bez niego baza zwraca wiersze w kolejności, która nie jest niczym zagwarantowana. Zrzut: kw4.jpg.
kwerendy.txtTekstzmienione: 5 linii
-- Zapytanie 1SELECT imie, miotFROM swinkiWHERE MONTH(data_ur) = 7;-- Zapytanie 2SELECT DISTINCT s.data_ur, s.miot, r.rasaFROM swinki AS sJOIN rasy AS r ON r.id = s.rasy_idWHERE r.id = 1;-- Zapytanie 3SELECT imie, cena, opisFROM swinkiWHERE rasy_id = 1;-- Zapytanie 4SELECT rasaFROM rasyORDER BY id;
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 8-18 · po tym etapie masz 17 z 40 kryteriów (pkt)
Krok 8: Kadrowanie crested.jpg do 500 × 330 px
Kryteria:
R.2.1 Grafikę crested.jpg skadrowano tak, że widoczny jest pysk zwierzęcia oraz wymiar grafiki to dokładnie 500 px szerokości i 330 px wysokości
ok. 3 min
Polecenie z arkusza
Grafikę crested.jpg, wypakowaną z archiwum, należy skadrować tak, aby rozmiar obrazu po kadrowaniu wynosił dokładnie 500 px szerokości na 330 px wysokości. Na skadrowanym obrazie musi być widoczny pysk zwierzęcia. Przykład kadru zaznaczono czarnym prostokątem na obrazie 3.
Grafika jest taka sama jak w wersji podstawowej. W GIMP-ie narzędzie Kadrowanie ze stałą wielkością 500 × 330 px, prostokąt na głowie z uszami (jak czarna ramka na obrazie 3), Obraz → Przytnij do zaznaczenia, eksport pod tą samą nazwą. To kadrowanie, nie skalowanie - piksele zostają te same. Po lewej oryginał z ramką, po prawej wynik.
Typowe błędy
Przeskalowanie obrazu do 500 × 330 zamiast kadrowania zniekształca proporcje - kryterium wymaga kadru.
R.2.2 Witrynę internetową zapisano w pliku peruwianka.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. 2 min
Polecenie z arkusza
Składa się ze stron o nazwach peruwianka.php, american.php, crested.php zapisanych w języku HTML5. Ustawiony język zawartości strony na polski. Jawnie zastosowany właściwy standard kodowania polskich znaków
Najpierw jedna strona, peruwianka.php - dwie pozostałe powstaną na końcu z gotowej, sprawdzonej strony. <!DOCTYPE html>, <html lang="pl"> i <meta charset="UTF-8"> jako pierwszy element <head> - razem R.2.2. Na egzaminie plik leży w htdocs XAMPP-a i otwierasz go przez http://localhost/....
R.3.6 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
Całe formatowanie pochodzi ze styl.css - bez atrybutów style w HTML-u (R.3.6).
Typowe błędy
Klucz odbiera R.3.6 także wtedy, gdy choć jeden selektor nie trafia w blok (np. kropka zamiast #).
R.2.4 Układ strony zdefiniowano dzieląc ją na bloki: banera, menu, główny, 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, dwa bloki lewe: blok menu i blok główny, jeden blok 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 <header>, menu <nav>, blok główny <main>, blok prawy <aside>, stopka <footer> (R.2.4). Kolejność to kolejność treści: nagłówek, menu, główna treść, dodatki. W wersji podstawowej <aside> musiał stać przed menu, bo blok pływający zaczyna się tam, gdzie stoi w kodzie; siatka CSS postawi go obok menu niezależnie od kolejności.
R.3.2 Odnośnik o treści "Rasa Peruwianka" inicjuje otwarcie strony peruwianka.php
ok. 1 min
Polecenie z arkusza
Zawartość lewego bloku menu: Odnośnik do pliku peruwianka.php, o treści „Rasa Peruwianka”
Odnośnik do tej samej strony, z atrybutem aria-current="page" - czytnik ekranu powie „bieżąca strona”. W kopiach strony atrybut przejdzie na ich własny odnośnik (R.3.2).
Krok 15: Menu: odnośniki do american.php i crested.php
Kryteria:
R.3.3 Odnośnik o treści "Rasa American" inicjuje otwarcie strony american.php lub odnośnik o treści "Rasa Crested" inicjuje otwarcie strony crested.php (kryterium spełnione nawet, gdy pliki nie istnieją)
ok. 1 min
Polecenie z arkusza
Odnośnik do pliku american.php, o treści „Rasa American”. Odnośnik do pliku crested.php, o treści „Rasa Crested”
Dwa kolejne odnośniki. Plików jeszcze nie ma - klucz uznaje odnośnik i tak (R.3.3), a pliki powstaną na końcu.
Krok 16: Blok prawy: nagłówek i pusta lista numerowana
Kryteria:
R.2.6 W prawym bloku umieszczono jedną listę numerowaną, zastosowano znaczniki ol, li (w skrypcie lub HTML)
ok. 1 min
Polecenie z arkusza
Zawartość prawego bloku: Nagłówek trzeciego stopnia o treści: „Poznaj wszystkie rasy świnek morskich”. Lista numerowana (uporządkowana) wypełniona elementami przez skrypt 1
<h3> i lista uporządkowana <ol> - numeruje elementy sama. Elementy <li> wypisze Skrypt 1 (R.2.6).
Krok 17: Blok główny: zdjęcie, linia pozioma, nagłówek
Kryteria: ,
R.2.7 W bloku głównym umieszczono obraz peruwianka.jpg z tekstem alternatywnym: „Świnka morska rasy peruwianka”
R.2.8 W bloku głównym umieszczono linię poziomą
ok. 2 min
Polecenie z arkusza
Zawartość lewego bloku głównego: Obraz peruwianka.jpg z tekstem alternatywnym: „Świnka morska rasy peruwianka”. Efekt działania skryptu 2. Linia pozioma. Nagłówek drugiego stopnia o treści: „Świnki w tym miocie”. Efekt działania skryptu 3
Zdjęcie z tekstem alternatywnym (R.2.7), linia pozioma <hr> (R.2.8) i <h2>. Między zdjęciem a linią stanie wynik Skryptu 2, pod nagłówkiem - Skryptu 3.
R.2.5 W banerze zapisano nagłówek h1: "Hodowla świnek morskich - zamów świnkowe maluszki" , w bloku głównym h2: "Świnki w tym miocie" , w bloku prawym h3: "Poznaj wszystkie rasy świnek morskich" oraz w stopce paragraf z numerem zdającego
ok. 1 min
Polecenie z arkusza
Zawartość stopki: Paragraf (akapit) o treści: „Stronę wykonał: ”, dalej wstawiony numer zdającego
Akapit w <footer>. Na egzaminie po dwukropku wpisujesz swój numer zdającego (PESEL), tu stoi autor rozwiązania. Z nagłówkami h1, h2, h3 to R.2.5.
Domyślne formatowanie wszystkich selektorów: krój czcionki Helvetica
Dwa kolory z arkusza w zmiennych: SaddleBrown (baner, stopka) i Peru (menu, blok prawy). Selektor * z Helvetiką i krojami zapasowymi: Helvetica jest standardem na komputerach Apple, na Windowsie zwykle jej nie ma - wtedy przeglądarka weźmie podobny Arial, a w ostateczności dowolny krój bezszeryfowy (R.4.1).
R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z obrazem 2 w arkuszu (prawidłowo zastosowano właściwości CSS decydujące o układzie strony, np. float i clear albo display flex albo grid)
ok. 3 min
Polecenie z arkusza
Podział strony na bloki: baner, dwa bloki lewe: blok menu i blok główny, jeden blok 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
grid-template-areas rysuje obraz 2 słowami: baner na całą szerokość, w lewej kolumnie menu i pod nim blok główny, w prawej - blok prawy przez oba wiersze, na dole stopka. grid-template-columns: 80% 20% to od razu szerokości z arkusza (klucz R.4.5 przyjmuje je w tej postaci). align-items: start - bloki mają wysokości z arkusza, zamiast rozciągać się do wiersza.
Każdy blok dostaje nazwę pola (grid-area). Bez float nie ma clear - stopka ma swój wiersz (R.3.1).
Dla lewego bloku menu: kolor tła Peru, szerokość 80%, wysokość 40 px, margines wewnętrzny górny 20 px
Szerokość 80% daje kolumna. Blok menu ma 40 px wysokości i 20 px marginesu u góry, razem 60 px - z 700 px bloku głównego to dokładnie 760 px bloku prawego.
Typowe błędy
width: 80% dopisane do menu w kolumnie 80% daje blok szeroki na 64% strony - procent szerokości elementu siatki liczy się od jego kolumny.
R.4.8 Ustawiono paski przewijania dla bloku głównego (overflow:auto lub scroll)
ok. 1 min
Polecenie z arkusza
Dla lewego bloku głównego: szerokość 80%, wysokość 700 px, rozmiar czcionki 120%, paski przewijania pojawiające się tylko, gdy tekst nie mieści się w oknie
overflow: auto - pasek przewijania tylko wtedy, gdy treść jest wyższa niż 700 px (R.4.8).
R.4.3 Ustawiono biały kolor czcionki dla banera, stopki i bloku prawego oraz #DDD dla selektora odnośnika
R.4.6 Ustawiono cechy tekstu: wyrównanie do środka dla banera i stopki, rozmiar 120% dla bloku głównego i 140% dla odnośnika oraz brak podkreślenia dla odnośnika (text- decoration:none)
ok. 2 min
Polecenie z arkusza
Dla selektora odnośnika: kolor czcionki #DDD, margines wewnętrzny lewy 90 px, rozmiar czcionki 140%, brak podkreślenia
Selektor znacznika a - uwaga w arkuszu i w kluczu: wyłącznie selektor znacznika, nie nav a ani klasa (tu projekt arkusza ma pierwszeństwo przed wygodą). Biel bloków i #DDD odnośników to R.4.3, cechy tekstu - R.4.6.
Typowe błędy
Reguła nav a albo klasa odnośnika nie spełnia R.4.3 ani R.4.7 - klucz wymaga samego selektora a.
R.4.7 Ustawiono marginesy wewnętrzne (padding) dla banera i stopki 7px, górny dla bloku menu 20px, lewy dla odnośnika 90px oraz marginesy zewnętrzne (margin) dla selektora img 30px
R.4.9 Ustawiono dla obrazu opływanie tekstem po prawej stronie (np. float: left;)
ok. 1 min
Polecenie z arkusza
Dla selektora obrazu: opływanie tekstem po prawej stronie (obraz znajduje się po lewej stronie), marginesy zewnętrzne 30 px
Tu float zostaje, bo robi to, do czego powstał: opływanie obrazu tekstem - arkusz mówi o tym wprost, a klucz R.4.9 podaje float: left. Siatka układa bloki strony, float - obraz w tekście. Selektor znacznika img, jak każe uwaga arkusza (R.4.7, R.4.9).
Kroki 28-37 · po tym etapie masz 38 z 40 kryteriów (pkt)
Krok 28: Połączenie z bazą na górze pliku i zamknięcie
Kryteria: ,
R.5.1 Skrypt zawiera instrukcje połączenia z serwerem bazy danych i wyboru bazy hodowla
R.5.2 Ostatnią operacją na bazie jest jej zamknięcie
ok. 4 min
Polecenie z arkusza
Skrypty łączą się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie hodowla
Wszystkie dane strona pobierze przed HTML-em, w jednym bloku PHP na samej górze pliku. W HTML-u zostanie potem tylko wypisywanie - kod rozmawiający z bazą jest w jednym miejscu, a połączenie da się zamknąć, zanim przeglądarka dostanie pierwszy znacznik.
$breedId - identyfikator rasy w jednej zmiennej; kopie strony zmienią tylko tę linię,
new PDO(...) - połączenie z serwerem localhost, bazą hodowla i kodowaniem utf8mb4, użytkownik root bez hasła (R.5.1). ERRMODE_EXCEPTION - każdy błąd bazy rzuca wyjątek, zamiast zwracać false, którego łatwo nie zauważyć; FETCH_ASSOC - wiersze jako tablice z nazwami kolumn,
$pdo = null - PDO nie ma funkcji „zamknij”: połączenie zamyka się, gdy znika ostatnie odwołanie do obiektu. Stoi na końcu bloku, więc jest ostatnią operacją na bazie (R.5.2),
try / catch (PDOException ...) - gdy baza nie działa, strona nie pokaże uczniowi komunikatu PHP ze szczegółami serwera, tylko zwykłe zdanie.
PDO zamiast mysqli - klucz przyjmuje obie biblioteki (uwaga przy R.5). Od tego kroku podgląd to wynik prawdziwego uruchomienia strony.
peruwianka.phpPHPzmienione: 14 linii
<?php$breedId = 1; // jedyna linia, którą różnią się kopie: american.php - 6, crested.php - 7try {$pdo = new PDO('mysql:host=localhost;dbname=hodowla;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);$pdo = null; // zamknięcie połączenia - ostatnia operacja na bazie} catch (PDOException $exception) {$databaseError = 'Nie udało się pobrać danych z bazy. Spróbuj odświeżyć stronę za chwilę.';}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Hodowla świnek morskich</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Hodowla świnek morskich - zamów świnkowe maluszki</h1> </header> <nav> <ahref="peruwianka.php"aria-current="page">Rasa Peruwianka</a> <ahref="american.php">Rasa American</a> <ahref="crested.php">Rasa Crested</a> </nav> <main> <imgsrc="peruwianka.jpg"alt="Świnka morska rasy peruwianka"> <hr> <h2>Świnki w tym miocie</h2> </main> <aside> <h3>Poznaj wszystkie rasy świnek morskich</h3> <ol> </ol> </aside> <footer> <p>Stronę wykonał: Bartosz Bryniarski</p> </footer></body></html>
Podgląd strony po tym kroku (peruwianka.php)
Krok 29: Skrypt 1: zapytanie 4
Kryteria:
R.5.3 Skrypt 1 zawiera instrukcje wysyłające do bazy danych zapytanie 4 lub skrypt 2: zapytanie 2 lub skrypt 3: zapytanie 3
ok. 2 min
Polecenie z arkusza
Skrypt 1: Wysyła do bazy danych zapytanie 4
Zapytanie bez danych od użytkownika, więc wystarczy query. fetchAll(PDO::FETCH_COLUMN) zwraca od razu prostą listę wartości pierwszej kolumny: ["peruwianka", "angora", ...] - bez tablic w tablicy. W catch lista dostaje wartość pustą, żeby HTML niżej nie trafił na niezdefiniowaną zmienną (R.5.3). Na stronie jeszcze nic nie widać.
peruwianka.phpPHPzmienione: 4 linie
<?php$breedId = 1; // jedyna linia, którą różnią się kopie: american.php - 6, crested.php - 7try {$pdo = new PDO('mysql:host=localhost;dbname=hodowla;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);// Skrypt 1: zapytanie 4 - wszystkie rasy$breeds = $pdo->query('SELECT rasa FROM rasy ORDER BY id')->fetchAll(PDO::FETCH_COLUMN);$pdo = null; // zamknięcie połączenia - ostatnia operacja na bazie} catch (PDOException $exception) {$breeds = [];$databaseError = 'Nie udało się pobrać danych z bazy. Spróbuj odświeżyć stronę za chwilę.';}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Hodowla świnek morskich</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Hodowla świnek morskich - zamów świnkowe maluszki</h1> </header> <nav> <ahref="peruwianka.php"aria-current="page">Rasa Peruwianka</a> <ahref="american.php">Rasa American</a> <ahref="crested.php">Rasa Crested</a> </nav> <main> <imgsrc="peruwianka.jpg"alt="Świnka morska rasy peruwianka"> <hr> <h2>Świnki w tym miocie</h2> </main> <aside> <h3>Poznaj wszystkie rasy świnek morskich</h3> <ol> </ol> </aside> <footer> <p>Stronę wykonał: Bartosz Bryniarski</p> </footer></body></html>
R.5.4 Skrypt 1 wyświetla w bloku prawym zwrócone zapytaniem rasy świnek morskich
R.5.9 Skrypt 1 lub 3 zapisano w oparciu o pętlę o liczbie iteracji równej liczbie zwróconych wierszy
ok. 3 min
Polecenie z arkusza
Zwrócone zapytaniem rasy świnek morskich wypisuje jako elementy listy
foreach wykonuje się tyle razy, ile ras zwróciło zapytanie - 13 (R.5.9). Zapis z dwukropkiem i endforeach jest czytelniejszy w HTML-u niż klamry rozrzucone między znacznikami,
<?= ... ?> to skrót od <?php echo ... ?>,
funkcja e() (na górze pliku) przepuszcza każdy tekst z bazy przez htmlspecialchars - znak < albo cudzysłów w danych nie rozbije strony ani nie wstrzyknie do niej kodu. Przy okazji trim usuwa spację z początku rasy „ somali” zapisanej tak w bazie.
Lista w bloku prawym: 1. peruwianka ... 13. skinny (R.5.4).
peruwianka.phpPHPzmienione: 8 linii
<?php$breedId = 1; // jedyna linia, którą różnią się kopie: american.php - 6, crested.php - 7functione(?string $text): string{returnhtmlspecialchars(trim($text ?? ''), ENT_QUOTES);}try {$pdo = new PDO('mysql:host=localhost;dbname=hodowla;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);// Skrypt 1: zapytanie 4 - wszystkie rasy$breeds = $pdo->query('SELECT rasa FROM rasy ORDER BY id')->fetchAll(PDO::FETCH_COLUMN);$pdo = null; // zamknięcie połączenia - ostatnia operacja na bazie} catch (PDOException $exception) {$breeds = [];$databaseError = 'Nie udało się pobrać danych z bazy. Spróbuj odświeżyć stronę za chwilę.';}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Hodowla świnek morskich</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Hodowla świnek morskich - zamów świnkowe maluszki</h1> </header> <nav> <ahref="peruwianka.php"aria-current="page">Rasa Peruwianka</a> <ahref="american.php">Rasa American</a> <ahref="crested.php">Rasa Crested</a> </nav> <main> <imgsrc="peruwianka.jpg"alt="Świnka morska rasy peruwianka"> <hr> <h2>Świnki w tym miocie</h2> </main> <aside> <h3>Poznaj wszystkie rasy świnek morskich</h3> <ol><?phpforeach ($breedsas$breed): ?> <li><?= e($breed) ?></li><?phpendforeach; ?> </ol> </aside> <footer> <p>Stronę wykonał: Bartosz Bryniarski</p> </footer></body></html>
Podgląd strony po tym kroku (peruwianka.php)
Krok 31: Skrypt 2: zapytanie 2
ok. 3 min
Polecenie z arkusza
Skrypt 2: Wysyła do bazy danych zapytanie 2
Zapytanie przygotowane: w miejscu identyfikatora stoi parametr :breed, a wartość podaje execute(["breed" => $breedId]). Baza dostaje treść zapytania i dane osobno, więc dana nigdy nie stanie się częścią kodu SQL - nawet gdyby identyfikator przyszedł kiedyś z adresu strony. Dzięki DISTINCT wynikiem jest jeden wiersz: wystarczy fetch() bez pętli (zwraca false, gdy wiersza nie ma).
peruwianka.phpPHPzmienione: 7 linii
<?php$breedId = 1; // jedyna linia, którą różnią się kopie: american.php - 6, crested.php - 7functione(?string $text): string{returnhtmlspecialchars(trim($text ?? ''), ENT_QUOTES);}try {$pdo = new PDO('mysql:host=localhost;dbname=hodowla;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);// Skrypt 1: zapytanie 4 - wszystkie rasy$breeds = $pdo->query('SELECT rasa FROM rasy ORDER BY id')->fetchAll(PDO::FETCH_COLUMN);// Skrypt 2: zapytanie 2 - dane miotu wybranej rasy$statement = $pdo->prepare('SELECT DISTINCT s.data_ur, s.miot, r.rasa FROM swinki AS s JOIN rasy AS r ON r.id = s.rasy_id WHERE r.id = :breed');$statement->execute(['breed' => $breedId]);$litter = $statement->fetch();$pdo = null; // zamknięcie połączenia - ostatnia operacja na bazie} catch (PDOException $exception) {$breeds = [];$litter = false;$databaseError = 'Nie udało się pobrać danych z bazy. Spróbuj odświeżyć stronę za chwilę.';}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Hodowla świnek morskich</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Hodowla świnek morskich - zamów świnkowe maluszki</h1> </header> <nav> <ahref="peruwianka.php"aria-current="page">Rasa Peruwianka</a> <ahref="american.php">Rasa American</a> <ahref="crested.php">Rasa Crested</a> </nav> <main> <imgsrc="peruwianka.jpg"alt="Świnka morska rasy peruwianka"> <hr> <h2>Świnki w tym miocie</h2> </main> <aside> <h3>Poznaj wszystkie rasy świnek morskich</h3> <ol><?phpforeach ($breedsas$breed): ?> <li><?= e($breed) ?></li><?phpendforeach; ?> </ol> </aside> <footer> <p>Stronę wykonał: Bartosz Bryniarski</p> </footer></body></html>
R.5.5 Skrypt 2 wyświetla w bloku głównym zwróconą zapytaniem rasę świnki morskiej
ok. 2 min
Polecenie z arkusza
Wyświetla dane pobrane z bazy danych, w następujący sposób: W nagłówku drugiego stopnia treść „Rasa: <rasa>”
Pola po nazwach kolumn ($litter["rasa"]), nie po numerach - kolejność pól w SELECT może się zmienić, a kod dalej działa. if ($litter) - nagłówek tylko wtedy, gdy miot istnieje. Obok zdjęcia: „Rasa: peruwianka” (R.5.5).
peruwianka.phpPHPzmienione: 3 linie
<?php$breedId = 1; // jedyna linia, którą różnią się kopie: american.php - 6, crested.php - 7functione(?string $text): string{returnhtmlspecialchars(trim($text ?? ''), ENT_QUOTES);}try {$pdo = new PDO('mysql:host=localhost;dbname=hodowla;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);// Skrypt 1: zapytanie 4 - wszystkie rasy$breeds = $pdo->query('SELECT rasa FROM rasy ORDER BY id')->fetchAll(PDO::FETCH_COLUMN);// Skrypt 2: zapytanie 2 - dane miotu wybranej rasy$statement = $pdo->prepare('SELECT DISTINCT s.data_ur, s.miot, r.rasa FROM swinki AS s JOIN rasy AS r ON r.id = s.rasy_id WHERE r.id = :breed');$statement->execute(['breed' => $breedId]);$litter = $statement->fetch();$pdo = null; // zamknięcie połączenia - ostatnia operacja na bazie} catch (PDOException $exception) {$breeds = [];$litter = false;$databaseError = 'Nie udało się pobrać danych z bazy. Spróbuj odświeżyć stronę za chwilę.';}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Hodowla świnek morskich</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Hodowla świnek morskich - zamów świnkowe maluszki</h1> </header> <nav> <ahref="peruwianka.php"aria-current="page">Rasa Peruwianka</a> <ahref="american.php">Rasa American</a> <ahref="crested.php">Rasa Crested</a> </nav> <main> <imgsrc="peruwianka.jpg"alt="Świnka morska rasy peruwianka"><?phpif ($litter): ?> <h2>Rasa: <?= e($litter['rasa']) ?></h2><?phpendif; ?> <hr> <h2>Świnki w tym miocie</h2> </main> <aside> <h3>Poznaj wszystkie rasy świnek morskich</h3> <ol><?phpforeach ($breedsas$breed): ?> <li><?= e($breed) ?></li><?phpendforeach; ?> </ol> </aside> <footer> <p>Stronę wykonał: Bartosz Bryniarski</p> </footer></body></html>
Podgląd strony po tym kroku (peruwianka.php)
Krok 33: Skrypt 2: data urodzenia i miot
Kryteria:
R.5.6 Skrypt 2 wyświetla zwróconą zapytaniem datę urodzenia i miot
ok. 1 min
Polecenie z arkusza
W paragrafie treść „Data urodzenia: <data-ur>”. W paragrafie treść „Oznaczenie miotu: <miot>”, gdzie dane zapisane w nawiasach <> wybrane zostały z bazy danych
Dwa akapity z tego samego wiersza: 2022-06-02 (format RRRR-MM-DD, jak na obrazie 2) i I5 (R.5.6).
peruwianka.phpPHPzmienione: 2 linie
<?php$breedId = 1; // jedyna linia, którą różnią się kopie: american.php - 6, crested.php - 7functione(?string $text): string{returnhtmlspecialchars(trim($text ?? ''), ENT_QUOTES);}try {$pdo = new PDO('mysql:host=localhost;dbname=hodowla;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);// Skrypt 1: zapytanie 4 - wszystkie rasy$breeds = $pdo->query('SELECT rasa FROM rasy ORDER BY id')->fetchAll(PDO::FETCH_COLUMN);// Skrypt 2: zapytanie 2 - dane miotu wybranej rasy$statement = $pdo->prepare('SELECT DISTINCT s.data_ur, s.miot, r.rasa FROM swinki AS s JOIN rasy AS r ON r.id = s.rasy_id WHERE r.id = :breed');$statement->execute(['breed' => $breedId]);$litter = $statement->fetch();$pdo = null; // zamknięcie połączenia - ostatnia operacja na bazie} catch (PDOException $exception) {$breeds = [];$litter = false;$databaseError = 'Nie udało się pobrać danych z bazy. Spróbuj odświeżyć stronę za chwilę.';}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Hodowla świnek morskich</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Hodowla świnek morskich - zamów świnkowe maluszki</h1> </header> <nav> <ahref="peruwianka.php"aria-current="page">Rasa Peruwianka</a> <ahref="american.php">Rasa American</a> <ahref="crested.php">Rasa Crested</a> </nav> <main> <imgsrc="peruwianka.jpg"alt="Świnka morska rasy peruwianka"><?phpif ($litter): ?> <h2>Rasa: <?= e($litter['rasa']) ?></h2> <p>Data urodzenia: <?= e($litter['data_ur']) ?></p> <p>Oznaczenie miotu: <?= e($litter['miot']) ?></p><?phpendif; ?> <hr> <h2>Świnki w tym miocie</h2> </main> <aside> <h3>Poznaj wszystkie rasy świnek morskich</h3> <ol><?phpforeach ($breedsas$breed): ?> <li><?= e($breed) ?></li><?phpendforeach; ?> </ol> </aside> <footer> <p>Stronę wykonał: Bartosz Bryniarski</p> </footer></body></html>
Podgląd strony po tym kroku (peruwianka.php)
Krok 34: Skrypt 3: zapytanie 3
ok. 3 min
Polecenie z arkusza
Skrypt 3: Wysyła do bazy danych zapytanie 3
Drugie zapytanie przygotowane z tym samym parametrem :breed - ta sama zmienna $breedId steruje oboma zapytaniami, więc nie da się poprawić jednego i zapomnieć o drugim. fetchAll() - wszystkie wiersze naraz. Przed zamknięciem połączenia $statement = null zwalnia ostatnie zapytanie: połączenie PDO zamyka się dopiero wtedy, gdy nie odwołuje się do niego już żaden obiekt.
peruwianka.phpPHPzmienione: 7 linii
<?php$breedId = 1; // jedyna linia, którą różnią się kopie: american.php - 6, crested.php - 7functione(?string $text): string{returnhtmlspecialchars(trim($text ?? ''), ENT_QUOTES);}try {$pdo = new PDO('mysql:host=localhost;dbname=hodowla;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);// Skrypt 1: zapytanie 4 - wszystkie rasy$breeds = $pdo->query('SELECT rasa FROM rasy ORDER BY id')->fetchAll(PDO::FETCH_COLUMN);// Skrypt 2: zapytanie 2 - dane miotu wybranej rasy$statement = $pdo->prepare('SELECT DISTINCT s.data_ur, s.miot, r.rasa FROM swinki AS s JOIN rasy AS r ON r.id = s.rasy_id WHERE r.id = :breed');$statement->execute(['breed' => $breedId]);$litter = $statement->fetch();// Skrypt 3: zapytanie 3 - świnki z miotu$statement = $pdo->prepare('SELECT imie, cena, opis FROM swinki WHERE rasy_id = :breed');$statement->execute(['breed' => $breedId]);$pigs = $statement->fetchAll();$statement = null;$pdo = null; // zamknięcie połączenia - ostatnia operacja na bazie} catch (PDOException $exception) {$breeds = [];$litter = false;$pigs = [];$databaseError = 'Nie udało się pobrać danych z bazy. Spróbuj odświeżyć stronę za chwilę.';}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Hodowla świnek morskich</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Hodowla świnek morskich - zamów świnkowe maluszki</h1> </header> <nav> <ahref="peruwianka.php"aria-current="page">Rasa Peruwianka</a> <ahref="american.php">Rasa American</a> <ahref="crested.php">Rasa Crested</a> </nav> <main> <imgsrc="peruwianka.jpg"alt="Świnka morska rasy peruwianka"><?phpif ($litter): ?> <h2>Rasa: <?= e($litter['rasa']) ?></h2> <p>Data urodzenia: <?= e($litter['data_ur']) ?></p> <p>Oznaczenie miotu: <?= e($litter['miot']) ?></p><?phpendif; ?> <hr> <h2>Świnki w tym miocie</h2> </main> <aside> <h3>Poznaj wszystkie rasy świnek morskich</h3> <ol><?phpforeach ($breedsas$breed): ?> <li><?= e($breed) ?></li><?phpendforeach; ?> </ol> </aside> <footer> <p>Stronę wykonał: Bartosz Bryniarski</p> </footer></body></html>
R.5.7 Skrypt 3 wyświetla w bloku głównym zwrócone z bazy imię i cenę
ok. 2 min
Polecenie z arkusza
Wyświetla dane pobrane z bazy danych, w następujący sposób: W nagłówku trzeciego stopnia treść „<imie> - <cena> zł”
Pętla foreach po świnkach: „Cindy - 200 zł”, „Wendy - 200 zł”, „Mała - 250 zł”, „Lola - 200 zł” (R.5.7). Cena przechodzi przez e() jak każda dana z bazy - funkcja przyjmuje też liczbę.
peruwianka.phpPHPzmienione: 3 linie
<?php$breedId = 1; // jedyna linia, którą różnią się kopie: american.php - 6, crested.php - 7functione(?string $text): string{returnhtmlspecialchars(trim($text ?? ''), ENT_QUOTES);}try {$pdo = new PDO('mysql:host=localhost;dbname=hodowla;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);// Skrypt 1: zapytanie 4 - wszystkie rasy$breeds = $pdo->query('SELECT rasa FROM rasy ORDER BY id')->fetchAll(PDO::FETCH_COLUMN);// Skrypt 2: zapytanie 2 - dane miotu wybranej rasy$statement = $pdo->prepare('SELECT DISTINCT s.data_ur, s.miot, r.rasa FROM swinki AS s JOIN rasy AS r ON r.id = s.rasy_id WHERE r.id = :breed');$statement->execute(['breed' => $breedId]);$litter = $statement->fetch();// Skrypt 3: zapytanie 3 - świnki z miotu$statement = $pdo->prepare('SELECT imie, cena, opis FROM swinki WHERE rasy_id = :breed');$statement->execute(['breed' => $breedId]);$pigs = $statement->fetchAll();$statement = null;$pdo = null; // zamknięcie połączenia - ostatnia operacja na bazie} catch (PDOException $exception) {$breeds = [];$litter = false;$pigs = [];$databaseError = 'Nie udało się pobrać danych z bazy. Spróbuj odświeżyć stronę za chwilę.';}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Hodowla świnek morskich</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Hodowla świnek morskich - zamów świnkowe maluszki</h1> </header> <nav> <ahref="peruwianka.php"aria-current="page">Rasa Peruwianka</a> <ahref="american.php">Rasa American</a> <ahref="crested.php">Rasa Crested</a> </nav> <main> <imgsrc="peruwianka.jpg"alt="Świnka morska rasy peruwianka"><?phpif ($litter): ?> <h2>Rasa: <?= e($litter['rasa']) ?></h2> <p>Data urodzenia: <?= e($litter['data_ur']) ?></p> <p>Oznaczenie miotu: <?= e($litter['miot']) ?></p><?phpendif; ?> <hr> <h2>Świnki w tym miocie</h2><?phpforeach ($pigsas$pig): ?> <h3><?= e($pig['imie']) ?> - <?= e($pig['cena']) ?> zł</h3><?phpendforeach; ?> </main> <aside> <h3>Poznaj wszystkie rasy świnek morskich</h3> <ol><?phpforeach ($breedsas$breed): ?> <li><?= e($breed) ?></li><?phpendforeach; ?> </ol> </aside> <footer> <p>Stronę wykonał: Bartosz Bryniarski</p> </footer></body></html>
Podgląd strony po tym kroku (peruwianka.php)
Krok 36: Skrypt 3: opis w akapicie
Kryteria: ,
R.5.8 Skrypt 3 wyświetla zwrócony zapytaniem opis
R.5.10 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
W paragrafie zwrócony zapytaniem opis. Na końcu jest zamykane połączenie z serwerem.
Opis pod nagłówkiem; pierwszy układa się obok zdjęcia, dalsze na całej szerokości, a blok główny dostaje pasek przewijania (obraz 2). Połączenie jest już zamknięte - na górze pliku, po ostatnim zapytaniu. Nazwy mówią, co przechowują: $breedId, $breeds, $litter, $pigs, $statement, e() (R.5.8, R.5.10).
peruwianka.phpPHPzmienione: 1 linia
<?php$breedId = 1; // jedyna linia, którą różnią się kopie: american.php - 6, crested.php - 7functione(?string $text): string{returnhtmlspecialchars(trim($text ?? ''), ENT_QUOTES);}try {$pdo = new PDO('mysql:host=localhost;dbname=hodowla;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);// Skrypt 1: zapytanie 4 - wszystkie rasy$breeds = $pdo->query('SELECT rasa FROM rasy ORDER BY id')->fetchAll(PDO::FETCH_COLUMN);// Skrypt 2: zapytanie 2 - dane miotu wybranej rasy$statement = $pdo->prepare('SELECT DISTINCT s.data_ur, s.miot, r.rasa FROM swinki AS s JOIN rasy AS r ON r.id = s.rasy_id WHERE r.id = :breed');$statement->execute(['breed' => $breedId]);$litter = $statement->fetch();// Skrypt 3: zapytanie 3 - świnki z miotu$statement = $pdo->prepare('SELECT imie, cena, opis FROM swinki WHERE rasy_id = :breed');$statement->execute(['breed' => $breedId]);$pigs = $statement->fetchAll();$statement = null;$pdo = null; // zamknięcie połączenia - ostatnia operacja na bazie} catch (PDOException $exception) {$breeds = [];$litter = false;$pigs = [];$databaseError = 'Nie udało się pobrać danych z bazy. Spróbuj odświeżyć stronę za chwilę.';}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Hodowla świnek morskich</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Hodowla świnek morskich - zamów świnkowe maluszki</h1> </header> <nav> <ahref="peruwianka.php"aria-current="page">Rasa Peruwianka</a> <ahref="american.php">Rasa American</a> <ahref="crested.php">Rasa Crested</a> </nav> <main> <imgsrc="peruwianka.jpg"alt="Świnka morska rasy peruwianka"><?phpif ($litter): ?> <h2>Rasa: <?= e($litter['rasa']) ?></h2> <p>Data urodzenia: <?= e($litter['data_ur']) ?></p> <p>Oznaczenie miotu: <?= e($litter['miot']) ?></p><?phpendif; ?> <hr> <h2>Świnki w tym miocie</h2><?phpforeach ($pigsas$pig): ?> <h3><?= e($pig['imie']) ?> - <?= e($pig['cena']) ?> zł</h3> <p><?= e($pig['opis']) ?></p><?phpendforeach; ?> </main> <aside> <h3>Poznaj wszystkie rasy świnek morskich</h3> <ol><?phpforeach ($breedsas$breed): ?> <li><?= e($breed) ?></li><?phpendforeach; ?> </ol> </aside> <footer> <p>Stronę wykonał: Bartosz Bryniarski</p> </footer></body></html>
Podgląd strony po tym kroku (peruwianka.php)
Krok 37: Rasa bez świnek i awaria bazy: komunikaty
ok. 3 min
Dodatek spoza arkusza - klucz go nie ocenia. Strona ma teraz odpowiedź na trzy sytuacje, których dane z arkusza nie pokazują:
rasa bez miotu (fetch() zwrócił false) - zamiast pustego „Rasa: ” nagłówek „Brak miotu tej rasy” (else przy if),
brak świnek (pusta tablica $pigs) - akapit „W tej chwili nie ma świnek tej rasy na sprzedaż.”,
awaria bazy (catch) - komunikat z role="alert" (czytnik ekranu przeczyta go od razu), a reszta strony - menu, nagłówki, stopka - działa dalej, bo zmienne mają w catch wartości puste.
Sprawdzone na prawdziwym PHP: rasa 2 (szetlandzka, w tabeli swinki nie ma żadnej) daje oba komunikaty, a złe hasło do bazy - komunikat bez treści błędu serwera. Przy rasach 1, 6 i 7 strona wygląda tak jak wcześniej.
peruwianka.phpPHPzmienione: 8 linii
<?php$breedId = 1; // jedyna linia, którą różnią się kopie: american.php - 6, crested.php - 7functione(?string $text): string{returnhtmlspecialchars(trim($text ?? ''), ENT_QUOTES);}try {$pdo = new PDO('mysql:host=localhost;dbname=hodowla;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);// Skrypt 1: zapytanie 4 - wszystkie rasy$breeds = $pdo->query('SELECT rasa FROM rasy ORDER BY id')->fetchAll(PDO::FETCH_COLUMN);// Skrypt 2: zapytanie 2 - dane miotu wybranej rasy$statement = $pdo->prepare('SELECT DISTINCT s.data_ur, s.miot, r.rasa FROM swinki AS s JOIN rasy AS r ON r.id = s.rasy_id WHERE r.id = :breed');$statement->execute(['breed' => $breedId]);$litter = $statement->fetch();// Skrypt 3: zapytanie 3 - świnki z miotu$statement = $pdo->prepare('SELECT imie, cena, opis FROM swinki WHERE rasy_id = :breed');$statement->execute(['breed' => $breedId]);$pigs = $statement->fetchAll();$statement = null;$pdo = null; // zamknięcie połączenia - ostatnia operacja na bazie} catch (PDOException $exception) {$breeds = [];$litter = false;$pigs = [];$databaseError = 'Nie udało się pobrać danych z bazy. Spróbuj odświeżyć stronę za chwilę.';}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Hodowla świnek morskich</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Hodowla świnek morskich - zamów świnkowe maluszki</h1> </header> <nav> <ahref="peruwianka.php"aria-current="page">Rasa Peruwianka</a> <ahref="american.php">Rasa American</a> <ahref="crested.php">Rasa Crested</a> </nav> <main><?phpif (isset($databaseError)): ?> <prole="alert"><?= e($databaseError) ?></p><?phpendif; ?> <imgsrc="peruwianka.jpg"alt="Świnka morska rasy peruwianka"><?phpif ($litter): ?> <h2>Rasa: <?= e($litter['rasa']) ?></h2> <p>Data urodzenia: <?= e($litter['data_ur']) ?></p> <p>Oznaczenie miotu: <?= e($litter['miot']) ?></p><?phpelse: ?> <h2>Brak miotu tej rasy</h2><?phpendif; ?> <hr> <h2>Świnki w tym miocie</h2><?phpif (!$pigs): ?> <p>W tej chwili nie ma świnek tej rasy na sprzedaż.</p><?phpendif; ?><?phpforeach ($pigsas$pig): ?> <h3><?= e($pig['imie']) ?> - <?= e($pig['cena']) ?> zł</h3> <p><?= e($pig['opis']) ?></p><?phpendforeach; ?> </main> <aside> <h3>Poznaj wszystkie rasy świnek morskich</h3> <ol><?phpforeach ($breedsas$breed): ?> <li><?= e($breed) ?></li><?phpendforeach; ?> </ol> </aside> <footer> <p>Stronę wykonał: Bartosz Bryniarski</p> </footer></body></html>
Kroki 38-39 · po tym etapie masz 40 z 40 kryteriów (pkt)
Krok 38: Kopia american.php
Kryteria:
R.3.4 Na stronie american.php jest widoczny obraz american.jpg z tekstem alternatywnym „Świnka morska rasy american” oraz wyświetlają się informacje dotyczące rasy american
ok. 2 min
Polecenie z arkusza
Należy skopiować dwukrotnie dokument peruwianka.php i zmienić nazwy na american.php i crested.php. Zmiany, których należy dokonać w bloku głównym dokumentu american.php (obraz 4): Obraz: źródło american.jpg, tekst alternatywny „Świnka morska rasy american”. Skrypt 2: w zapytaniu 2 należy zmienić warunek zapytania, id rasy jest równe 6. Skrypt 3: w zapytaniu 3 należy zmienić warunek zapytania, id rasy jest równe 6
Kopia gotowej strony jako american.php. Warunki obu zapytań zmienia jedna linia: $breedId = 6; - wartość parametru :breed w zapytaniach 2 i 3. Do tego plik obrazu, tekst alternatywny i aria-current przy „Rasa American”. Podgląd (prawdziwe uruchomienie): rasa american, miot H4, świnki Crejzy, Biała i Lucy - jak na obrazie 4 (R.3.4).
american.phpPHPnowy plik
<?php$breedId = 6; // jedyna linia, którą różnią się kopie: american.php - 6, crested.php - 7functione(?string $text): string{returnhtmlspecialchars(trim($text ?? ''), ENT_QUOTES);}try {$pdo = new PDO('mysql:host=localhost;dbname=hodowla;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);// Skrypt 1: zapytanie 4 - wszystkie rasy$breeds = $pdo->query('SELECT rasa FROM rasy ORDER BY id')->fetchAll(PDO::FETCH_COLUMN);// Skrypt 2: zapytanie 2 - dane miotu wybranej rasy$statement = $pdo->prepare('SELECT DISTINCT s.data_ur, s.miot, r.rasa FROM swinki AS s JOIN rasy AS r ON r.id = s.rasy_id WHERE r.id = :breed');$statement->execute(['breed' => $breedId]);$litter = $statement->fetch();// Skrypt 3: zapytanie 3 - świnki z miotu$statement = $pdo->prepare('SELECT imie, cena, opis FROM swinki WHERE rasy_id = :breed');$statement->execute(['breed' => $breedId]);$pigs = $statement->fetchAll();$statement = null;$pdo = null; // zamknięcie połączenia - ostatnia operacja na bazie} catch (PDOException $exception) {$breeds = [];$litter = false;$pigs = [];$databaseError = 'Nie udało się pobrać danych z bazy. Spróbuj odświeżyć stronę za chwilę.';}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Hodowla świnek morskich</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Hodowla świnek morskich - zamów świnkowe maluszki</h1> </header> <nav> <ahref="peruwianka.php">Rasa Peruwianka</a> <ahref="american.php"aria-current="page">Rasa American</a> <ahref="crested.php">Rasa Crested</a> </nav> <main><?phpif (isset($databaseError)): ?> <prole="alert"><?= e($databaseError) ?></p><?phpendif; ?> <imgsrc="american.jpg"alt="Świnka morska rasy american"><?phpif ($litter): ?> <h2>Rasa: <?= e($litter['rasa']) ?></h2> <p>Data urodzenia: <?= e($litter['data_ur']) ?></p> <p>Oznaczenie miotu: <?= e($litter['miot']) ?></p><?phpelse: ?> <h2>Brak miotu tej rasy</h2><?phpendif; ?> <hr> <h2>Świnki w tym miocie</h2><?phpif (!$pigs): ?> <p>W tej chwili nie ma świnek tej rasy na sprzedaż.</p><?phpendif; ?><?phpforeach ($pigsas$pig): ?> <h3><?= e($pig['imie']) ?> - <?= e($pig['cena']) ?> zł</h3> <p><?= e($pig['opis']) ?></p><?phpendforeach; ?> </main> <aside> <h3>Poznaj wszystkie rasy świnek morskich</h3> <ol><?phpforeach ($breedsas$breed): ?> <li><?= e($breed) ?></li><?phpendforeach; ?> </ol> </aside> <footer> <p>Stronę wykonał: Bartosz Bryniarski</p> </footer></body></html>
Podgląd strony po tym kroku (american.php)
Krok 39: Kopia crested.php
Kryteria:
R.3.5 Na stronie crested.php jest widoczny obraz crested.jpg z tekstem alternatywnym „Świnka morska rasy crested” oraz wyświetlają się informacje dotyczące rasy crested
ok. 2 min
Polecenie z arkusza
Zmiany, których należy dokonać w bloku głównym dokumentu crested.php (obraz 5): Obraz: źródło crested.jpg, tekst alternatywny „Świnka morska rasy crested”. Skrypt 2: w zapytaniu 2 należy zmienić warunek zapytania, id rasy jest równe 7. Skrypt 3: w zapytaniu 3 należy zmienić warunek zapytania, id rasy jest równe 7
Druga kopia, crested.php: $breedId = 7;, wykadrowane zdjęcie crested.jpg z tekstem alternatywnym i aria-current przy „Rasa Crested”. Podgląd: miot G3 z 30 czerwca, Bąbelek i Lulu po 150 zł - jak na obrazie 5 (R.3.5).
crested.phpPHPnowy plik
<?php$breedId = 7; // jedyna linia, którą różnią się kopie: american.php - 6, crested.php - 7functione(?string $text): string{returnhtmlspecialchars(trim($text ?? ''), ENT_QUOTES);}try {$pdo = new PDO('mysql:host=localhost;dbname=hodowla;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);// Skrypt 1: zapytanie 4 - wszystkie rasy$breeds = $pdo->query('SELECT rasa FROM rasy ORDER BY id')->fetchAll(PDO::FETCH_COLUMN);// Skrypt 2: zapytanie 2 - dane miotu wybranej rasy$statement = $pdo->prepare('SELECT DISTINCT s.data_ur, s.miot, r.rasa FROM swinki AS s JOIN rasy AS r ON r.id = s.rasy_id WHERE r.id = :breed');$statement->execute(['breed' => $breedId]);$litter = $statement->fetch();// Skrypt 3: zapytanie 3 - świnki z miotu$statement = $pdo->prepare('SELECT imie, cena, opis FROM swinki WHERE rasy_id = :breed');$statement->execute(['breed' => $breedId]);$pigs = $statement->fetchAll();$statement = null;$pdo = null; // zamknięcie połączenia - ostatnia operacja na bazie} catch (PDOException $exception) {$breeds = [];$litter = false;$pigs = [];$databaseError = 'Nie udało się pobrać danych z bazy. Spróbuj odświeżyć stronę za chwilę.';}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Hodowla świnek morskich</title> <linkrel="stylesheet"href="styl.css"></head><body> <header> <h1>Hodowla świnek morskich - zamów świnkowe maluszki</h1> </header> <nav> <ahref="peruwianka.php">Rasa Peruwianka</a> <ahref="american.php">Rasa American</a> <ahref="crested.php"aria-current="page">Rasa Crested</a> </nav> <main><?phpif (isset($databaseError)): ?> <prole="alert"><?= e($databaseError) ?></p><?phpendif; ?> <imgsrc="crested.jpg"alt="Świnka morska rasy crested"><?phpif ($litter): ?> <h2>Rasa: <?= e($litter['rasa']) ?></h2> <p>Data urodzenia: <?= e($litter['data_ur']) ?></p> <p>Oznaczenie miotu: <?= e($litter['miot']) ?></p><?phpelse: ?> <h2>Brak miotu tej rasy</h2><?phpendif; ?> <hr> <h2>Świnki w tym miocie</h2><?phpif (!$pigs): ?> <p>W tej chwili nie ma świnek tej rasy na sprzedaż.</p><?phpendif; ?><?phpforeach ($pigsas$pig): ?> <h3><?= e($pig['imie']) ?> - <?= e($pig['cena']) ?> zł</h3> <p><?= e($pig['opis']) ?></p><?phpendforeach; ?> </main> <aside> <h3>Poznaj wszystkie rasy świnek morskich</h3> <ol><?phpforeach ($breedsas$breed): ?> <li><?= e($breed) ?></li><?phpendforeach; ?> </ol> </aside> <footer> <p>Stronę wykonał: Bartosz Bryniarski</p> </footer></body></html>
Podgląd strony po tym kroku (crested.php)
Etap 6: Porównanie z wersją podstawową
Krok 40 · po tym etapie masz 40 z 40 kryteriów (pkt)
Krok 40: Co jest inaczej i którą wersję wybrać na egzaminie
ok. 3 min
Obie wersje dają komplet 40 punktów. Różnice:
wersja podstawowa
wersja nowoczesna
układ
float bloków, <aside> w kodzie przed menu, clear stopki
grid-template-areas, kolejność treści w HTML-u
biblioteka
mysqli (funkcje z tabeli 1 arkusza)
PDO z wyjątkami
gdzie są zapytania
w trzech skryptach rozrzuconych po HTML-u
jeden blok na górze pliku, w HTML-u tylko pętle
identyfikator rasy
wpisany w dwa zapytania
parametr :breed ze zmiennej $breedId
odczyt wiersza
mysqli_fetch_row i $row[2]
FETCH_ASSOC i $litter["rasa"]
wypisywanie
dane z bazy wprost
e() - htmlspecialchars i trim
zamknięcie
mysqli_close na końcu Skryptu 3
$statement = null; $pdo = null; po ostatnim zapytaniu
brak danych, awaria bazy
ostrzeżenia PHP, puste nagłówki
komunikaty
Trzy prawie jednakowe pliki to w prawdziwym projekcie sygnał do wydzielenia wspólnej części do osobnego pliku (require) - tu arkusz każe kopiować całą stronę, a klucz sprawdza skrypty w plikach stron, więc obie wersje zostają przy kopiach.
Na egzaminie wersja podstawowa trzyma się funkcji z tabeli 1 arkusza i łatwiej ją napisać bez dokumentacji pod ręką. Nowoczesna jest bezpieczniejsza i trudniej w niej o pomyłkę przy kopiach - zmienia się jedna linia. Obie biblioteki klucz przyjmuje.
Krok 41 · po tym etapie masz 40 z 40 kryteriów (pkt)
Krok 41: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
UWAGA: 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 nazwa przeglądarki, w której sprawdzana była strona. W folderze z numerem zdającego: american.jpg, american.php, crested.jpg, crested.php, import.png, kw1.jpg - kw4.jpg, kwerendy.txt, peruwianka.jpg, peruwianka.php, przeglądarka.txt, styl.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.