Serwis używa plików cookies do analizy ruchu i poprawy działania. Szczegóły
EE.09-03-22.06-SGCzerwiec 2022 · 39 kroków · ok. 77 min · 36 kryteriów z klucza
Rozwiązanie krok po kroku: Opinie klientów hurtowni spożywczej (Nowoczesny kod (grid, PDO))
To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza hurtownia z czterema zapytaniami, zdjęcie ewa.jpg przeskalowane do szerokości 150 px i strona opinie.php z przewijanym blokiem opinii i czterema blokami stopki - i tak samo spełnia każde kryterium klucza. Inna jest droga:
jedna stopka <footer> jako siatka: cztery bloki stopki to sekcje w jej środku, a ich szerokości 25% opisuje grid-template-columns - bez float,
znaczniki opisujące rolę bloków: blok opinii to <article> - samodzielna wypowiedź klienta,
zmienne CSS dla kolorów z arkusza - Tomato, biały i DimGray są wpisane raz,
PHP na PDO na górze pliku, przed HTML-em: połączenie i oba zapytania w bloku try, zamknięcie połączenia w finally. W HTML-u zostają tylko pętle i wypisanie danych,
każda wartość z bazy przechodzi przez htmlspecialchars, a awaria bazy daje zwykłe zdanie zamiast komunikatu PHP z danymi serwera.
To arkusz EE.09 z czerwca 2022 - kwalifikacji formuły 2017, którą zastąpiła INF.03. Baza i zdjęcia pochodzą z oryginalnego archiwum CKE zad3.zip (załącznik na stronie arkusza), zapytania i zrzuty są policzone na MariaDB 10.4, a podgląd od kroków z PHP to wynik prawdziwego uruchomienia kodu w PHP 8.2 (klucz każe sprawdzać w XAMPP 8.1.2 - użyte konstrukcje działają w obu wersjach).
Jak liczą się punkty. Klucz ma 36 kryteriów (R.1.1 - R.5.8), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 27 punktów. Przy każdym kroku jest napisane, które kryteria spełnia; klucz przyjmuje zarówno mysqli, jak i PDO.
Suwak i strzałki obok niego - albo ←→ na klawiaturze - przechodzą krok po kroku; wyjaśnienie, pliki i podgląd zmieniają się razem z krokiem.
Lista „Etap” przenosi od razu do wybranego etapu.
„Rozwiązuję samodzielnie” chowa rozwiązanie kroku - najpierw własna próba, potem odsłonięcie.
„Tryb prezentacji” pokazuje same kroki, bez menu strony - na rzutnik.
Etap 1: Baza danych
Kroki 1-7 · po tym etapie masz 6 z 36 kryteriów (pkt)
Krok 1: Folder zdającego i archiwum zad3.zip
ok. 2 min
Polecenie z arkusza
Na pulpicie znajduje się archiwum o nazwie zad3.zip zabezpieczone hasłem: #_Opini3% 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.
Folder na pulpicie nazwany numerem PESEL (w tym rozwiązaniu w jego miejscu stoi Bartosz Bryniarski), do niego archiwum zad3.zip rozpakowane z hasłem #_Opini3%. W środku: baza.sql i pięć zdjęć klientów. Zdjęcia zostają obok strony - skrypt wpisze ich nazwy z bazy do atrybutu src.
Krok 2: XAMPP i pusta baza hurtownia
ok. 2 min
Polecenie z arkusza
Za pomocą narzędzia phpMyAdmin należy wykonać operacje na bazie danych: Utworzenie bazy danych o nazwie: hurtownia z zestawem polskich znaków (np. utf8_unicode_ci)
Start przy Apache i MySQL, potem http://localhost/phpmyadmin, Nowa, nazwa hurtownia, porównywanie utf8_unicode_ci, Utwórz.
Krok 3: Import pliku baza.sql i zrzut import.jpg
Kryteria:
R.1.1 Wykonano import tabel do bazy danych hurtownia , czynność udokumentowano plikiem o nazwie import w formacie JPEG
ok. 3 min
Polecenie z arkusza
Import tabel do bazy hurtownia z pliku baza.sql. Czynność należy udokumentować zrzutem ekranu, na którym powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel. Zrzut należy zapisać w formacie JPEG, pod nazwą import. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań.
Baza hurtownia, karta Import, plik baza.sql, Wykonaj. Po imporcie są trzy tabele: klienci (9 rekordów), opinie (6) i typy (3). Zrzut całego ekranu z komunikatem o sukcesie - import.jpg.
Podgląd strony po tym kroku
Krok 4: Zapytanie 1: trzech klientów z największą liczbą punktów
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 posortowane malejąco według punktów jedynie imię, nazwisko i punkty trzech klientów, których liczba punktów jest najwyższa. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, nazwisko, punkty FROM klienci ORDER BY punkty DESC LIMIT 3; oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczne są jedynie 3 wiersze w kolejności: Jan Nowak 3305, Judy Beck 3055, Ewa Nowakowska 2045
ok. 3 min
Polecenie z arkusza
Zapytania SQL na bazie hurtownia zapisane do pliku kwerendy.txt. Wykonanie kwerend należy udokumentować zrzutami w formacie PNG o nazwach kw1, kw2, kw3, kw4. Zrzuty powinny obejmować cały ekran monitora z widocznym paskiem zadań. Zapytanie 1: wybierające z tabeli Klienci posortowane malejąco według punktów jedynie imię, nazwisko i punkty trzech klientów, których liczba punktów jest najwyższa
ORDER BY punkty DESC sortuje od największej liczby punktów, LIMIT 3 zostawia trzy pierwsze wiersze. Wynik: Jan Nowak 3305, Judy Beck 3055, Ewa Nowakowska 2045. Zapytanie do kwerendy.txt (R.1.2), zrzut - kw1.png (R.1.3).
kwerendy.txtTekstnowy plik
-- Zapytanie 1SELECT imie, nazwisko, punktyFROM klienciORDER BY punkty DESCLIMIT 3;
Podgląd strony po tym kroku
Krok 5: Zapytanie 2: liczba klientów każdego typu
Kryteria:
R.1.4 Utworzono zapytanie 2 wybierające nazwę z tabeli Typy oraz liczbę klientów przypisanych do każdego typu. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa, COUNT(nazwa) FROM klienci JOIN typy ON Typy_id = typy.id GROUP BY nazwa; (możliwe COUNT(*), GROUP BY(Typy_id), GROUP BY (Typy.id), porównanie kluczy w WHERE) oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczne są dokładnie 3 wiersze: platynowy 2, złoty 3, zwykły 4
ok. 3 min
Polecenie z arkusza
Zapytanie 2: wybierające nazwę z tabeli Typy oraz liczbę klientów przypisanych do każdego typu. Należy posłużyć się relacją
Złączenie typów z klientami po Typy_id, COUNT(*) i GROUP BY nazwa - jedna liczba na typ. Wynik: platynowy 2, złoty 3, zwykły 4. Zrzut: kw2.png.
kwerendy.txtTekstzmienione: 6 linii
-- Zapytanie 1SELECT imie, nazwisko, punktyFROM klienciORDER BY punkty DESCLIMIT 3;-- Zapytanie 2SELECT nazwa, COUNT(*)FROM typyJOIN klienci ON typy.id = klienci.Typy_idGROUP BY nazwa;
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: zdjęcia, imiona i opinie klientów typu 2 i 3
Kryteria:
R.1.5 Utworzono zapytanie 3 wybierające jedynie pola zdjecie, imie z tabeli klienci oraz odpowiadające im pole opinia z tabeli opinie dla klientów, których typ ma id o wartości 2, 3. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT zdjecie, imie, opinia FROM klienci JOIN opinie ON klienci.id = klienci_id WHERE Typy_id=2 OR Typy_id=3; (lub porównanie kluczy po WHERE) oraz wynik działania zapytania udokumentowano zrzutem, na którym widocznych jest dokładnie 5 wierszy, jedynie pola zdjecie, imie, opinia dla imion: Anna, Ewa, Jan, John, Judy
ok. 3 min
Polecenie z arkusza
Zapytanie 3: wybierające jedynie pola zdjecie, imie z tabeli Klienci oraz odpowiadające im pole opinia z tabeli opinie dla klientów, których typ ma id o wartościach 2, 3. Należy posłużyć się relacją
Złączenie klientów z opiniami po Klienci_id i warunek Typy_id IN (2, 3). Wynik: 5 wierszy - Anna, Ewa, Jan, John i Judy. Zrzut: kw3.png. To zapytanie wykona skrypt 1.
kwerendy.txtTekstzmienione: 6 linii
-- Zapytanie 1SELECT imie, nazwisko, punktyFROM klienciORDER BY punkty DESCLIMIT 3;-- Zapytanie 2SELECT nazwa, COUNT(*)FROM typyJOIN klienci ON typy.id = klienci.Typy_idGROUP BY nazwa;-- Zapytanie 3SELECT zdjecie, imie, opiniaFROM klienciJOIN opinie ON klienci.id = opinie.Klienci_idWHERE Typy_id IN (2, 3);
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: nowa kolumna adres
Kryteria:
R.1.6 Utworzono zapytanie 4 dodające do tabeli klienci kolumnę o nazwie adres i typie napisowym, maksymalnie 50-znakowym. W pliku z kwerendami lub na zrzucie istnieje zapis np.: ALTER TABLE klienci ADD adres VARCHAR(50); (lub ADD COLUMN, typ text jest błędem) oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczny jest komunikat o pomyślnie wykonanym zapytaniu lub tabela z dodaną kolumną
ok. 2 min
Polecenie z arkusza
Zapytanie 4: dodające do tabeli Klienci kolumnę o nazwie adres i typie napisowym, maksymalnie 50-znakowym
ALTER TABLE zmienia strukturę tabeli, ADD adres VARCHAR(50) dokłada kolumnę napisową do 50 znaków (typ TEXT klucz uznaje za błąd). Komunikat „MySQL zwrócił pusty wynik” i kolumna adres w strukturze tabeli - zrzut kw4.png.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT imie, nazwisko, punktyFROM klienciORDER BY punkty DESCLIMIT 3;-- Zapytanie 2SELECT nazwa, COUNT(*)FROM typyJOIN klienci ON typy.id = klienci.Typy_idGROUP BY nazwa;-- Zapytanie 3SELECT zdjecie, imie, opiniaFROM klienciJOIN opinie ON klienci.id = opinie.Klienci_idWHERE Typy_id IN (2, 3);-- Zapytanie 4ALTER TABLE klienci ADD adres VARCHAR(50);
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 8-19 · po tym etapie masz 13 z 36 kryteriów (pkt)
Krok 8: Zdjęcie ewa.jpg: szerokość 150 px z zachowaniem proporcji
Kryteria:
R.2.1 Obraz w pliku ewa .jpg przeskalowano z zachowaniem proporcji do szerokości 150 px, odpowiadająca temu wysokość wynosi 200 px (± 2 px)
ok. 2 min
Polecenie z arkusza
Cechy grafiki ewa.jpg: Przeskalowana z zachowaniem proporcji do szerokości 150 px
Obraz → Skaluj obraz z zamkniętym łańcuchem, szerokość 150 px - wysokość wylicza się sama: z 317 × 423 px wychodzi 150 × 200 px, tyle samo co pozostałe zdjęcia. Eksport pod nazwą ewa.jpg (R.2.1).
Podgląd strony po tym kroku
Krok 9: Plik opinie.php z deklaracją HTML5
Kryteria:
R.2.2 Witrynę internetową zapisano w pliku o nazwie opinie.php
ok. 1 min
Polecenie z arkusza
Cechy witryny: Składa się ze strony o nazwie opinie.php Zapisana w języku HTML5
Plik opinie.php (R.2.2) od razu z <!DOCTYPE html> w pierwszej linii i szkieletem <html>, <head>, <body>.
R.2.3 Zapisano jawnie standard kodowania polskich znaków i deklarację HTML5 <!DOCTYPE HTML> oraz zadeklarowano dla witryny język polski (np. lang = 'pl')
ok. 1 min
Polecenie z arkusza
Jawnie zastosowany właściwy standard kodowania polskich znaków Zadeklarowany język witryny: polski
<meta charset="UTF-8"> jako pierwszy element <head> i lang="pl" w znaczniku <html> - deklaracja HTML5, kodowanie i język są gotowe (R.2.3).
R.3.3 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl3.css , formatowanie pochodzi jedynie z tego arkusza Uwaga: kryterium to nie jest spełnione również, gdy 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 styl3.css prawidłowo połączony z kodem strony
<link rel="stylesheet" href="styl3.css"> - całe formatowanie pochodzi z tego pliku (R.3.3).
Krok 13: Bloki: baner, główny i stopka z czterema sekcjami
Kryteria:
R.2.5 Wygląd strony zdefiniowano dzieląc ją na bloki: baner, główny i cztery bloki stopki. Zastosowano znaczniki sekcji
ok. 2 min
Polecenie z arkusza
Podział strony na bloki: baner, główny i cztery 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
Baner <header>, blok główny <main> i jedna stopka <footer> z czterema sekcjami <section> - to one są czterema blokami stopki (R.2.5). Stopka jest jedna, bo jest jedną częścią strony: kontenerem, który za chwilę ułoży swoje sekcje w siatkę. Selektor footer section trafi w każdą z nich bez klas i identyfikatorów.
Krok 16: Pierwszy blok stopki: nagłówek i odnośnik „Sklep 1”
Kryteria:
R.3.2 Na stronie umieszczono odnośnik, którego kliknięcie inicjuje otwarcie strony http://sklep.pl/
ok. 1 min
Polecenie z arkusza
Zawartość pierwszego bloku stopki: Nagłówek trzeciego stopnia o treści: „Współpracują z nami” Odnośnik o treści „Sklep 1” prowadzący do adresu http://sklep.pl/
<h3> i odnośnik z pełnym adresem, razem z http:// (R.3.2).
Krok 17: Drugi blok stopki: nagłówek i lista numerowana
ok. 1 min
Polecenie z arkusza
Zawartość drugiego bloku stopki: Nagłówek trzeciego stopnia o treści: „Nasi top klienci” Lista numerowana (uporządkowana), a w niej efekt działania skryptu 2
Kroki 20-26 · po tym etapie masz 18 z 36 kryteriów (pkt)
Krok 20: Plik styl3.css: kolory jako zmienne i krój dla wszystkich
Kryteria:
R.4.1 Ustawiono domyślną wartość dla wszystkich selektorów stylu CSS (*): krój czcionki Tahoma, sans-serif (czcionka Tahoma jako pierwsza)
ok. 2 min
Polecenie z arkusza
Styl CSS zdefiniowany w całości w zewnętrznym pliku o nazwie styl3.css. Domyślna wartość dla wszystkich selektorów stylu CSS: krój czcionki Tahoma, w przypadku braku sans-serif
Na początku zmienne CSS w :root: cztery kolory z arkusza dostają nazwy. Tomato i biały występują po kilka razy (baner, stopka, odnośnik), więc zmiana motywu to kilka linii na górze pliku.
Selektor * obejmuje każdy element: Tahoma, sans-serif (R.4.1).
Krok 23: Układ: stopka jako siatka czterech kolumn
Kryteria:
R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z Obrazem 2 w arkuszu egzaminacyjnym, nie należy uwzględniać bloków z opiniami (prawidłowo zastosowano właściwości CSS układające bloki na stronie, np. float albo display flex albo grid)
ok. 3 min
Polecenie z arkusza
Wspólne dla wszystkich bloków stopki: szerokość 25%. 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
Stopka staje się siatką: display: grid i grid-template-columns: repeat(4, 25%) - cztery kolumny po 25%. repeat(4, …) to skrót czterokrotnego wpisania 25%. Sekcje wypełniają kolumny po kolei, więc cztery bloki stoją obok siebie, a stopka zajmuje całą szerokość pod blokiem głównym - bez float i bez obawy, że czwarty blok spadnie do nowego wiersza (R.3.1).
R.4.2 Ustawiono kolor tła Tomato dla banera i wszystkich bloków stopki, Seashell dla bloku głównego
R.4.4 Ustawiono wysokość bloku głównego 500px i wszystkich bloków stopki 160px oraz szerokość wszystkich bloków stopki 25% (width lub grid-template-columns lub flex). Dla bloku głównego ustawiono paski przewijania overflow:auto;
ok. 2 min
Polecenie z arkusza
Wspólne dla wszystkich bloków stopki: kolor tła Tomato, biały kolor czcionki, wysokość 160 px
Selektor potomka footer section - każda sekcja wewnątrz stopki. Kolory tła banera, bloku głównego i bloków stopki są ustawione (R.4.2); wysokości, przewijanie i szerokości 25% przez grid-template-columns - też (klucz przyjmuje tę właściwość, R.4.4).
R.4.3 Ustawiono biały kolor czcionki dla banera, wszystkich bloków stopki i odnośnika
ok. 1 min
Polecenie z arkusza
Dla odnośnika: biały kolor czcionki
Biały kolor odnośników (R.4.3 - baner, bloki stopki i odnośnik). :focus-visible dokłada białą ramkę wokół odnośnika wybranego klawiszem Tab - na pomarańczowym tle domyślna ramka przeglądarki jest słabo widoczna.
Kroki 27-33 · po tym etapie masz 30 z 36 kryteriów (pkt)
Krok 27: Kod PHP na górze pliku i połączenie z bazą hurtownia
Kryteria:
R.5.1 Skrypt realizuje połączenie z serwerem bazy danych i wybór bazy hurtownia
ok. 4 min
Polecenie z arkusza
Skrypty łączą się z serwerem bazy danych na localhost, użytkownik root bez hasła, baza danych o nazwie hurtownia
Oba skrypty arkusza korzystają z tej samej bazy. Cały kod PHP stoi więc na samej górze opinie.php, przed <!DOCTYPE html>: najpierw komunikacja z bazą, potem HTML, który tylko wypisuje przygotowane dane.
e() - krótka funkcja z htmlspecialchars: każdy tekst z bazy zamienia <, >, &, cudzysłów i apostrof na encje, więc nie stanie się kodem strony,
new PDO(...) - serwer localhost, baza hurtownia i kodowanie w jednym napisie, potem root i puste hasło (R.5.1). ERRMODE_EXCEPTION - każdy błąd bazy rzuca wyjątek, FETCH_ASSOC - wiersze przychodzą jako tablice z nazwami kolumn ($opinion['imie'] zamiast $row[1]),
catch - gdy baza nie działa, szczegóły trafiają do dziennika błędów serwera (error_log), a w bloku głównym pojawia się zwykłe zdanie (trzy linie pod <h2>).
PDO zamiast funkcji mysqli z tabeli 1 - klucz przyjmuje obie biblioteki (uwaga przy R.5). Od tego kroku podgląd to wynik prawdziwego uruchomienia strony - na razie wygląda jak wcześniej.
Krok 28: Skrypt 1: zapytanie 3, blok opinii i zdjęcie
Kryteria: , ,
R.5.3 Przynajmniej jedno zapytanie zostało wysłane do bazy: skrypt 1 - zapytanie 3 lub skrypt 2 - zapytanie 1
R.5.5 Skrypt 1 dla każdego zwróconego wiersza wyświetla obraz, którego nazwa pliku jest pobrana z bazy
R.2.8 W bloku głównym umieszczono przynajmniej jeden obraz z tekstem alternatywnym "klient" (w skrypcie lub HTML)
ok. 4 min
Polecenie z arkusza
Działanie skryptu 1: Wysyła do bazy zapytanie 3. Każdy zwrócony zapytaniem wiersz wypisuje w osobnym bloku opinii, według wzoru: Obraz, którego nazwa pliku została pobrana z bazy danych, z tekstem alternatywnym „klient”
$pdo->query(...) - zapytanie 3 bez zmian (R.5.3); nie ma w nim danych od użytkownika, więc wystarczy zwykłe query,
->fetchAll() - od razu tablica wszystkich pięciu wierszy w $opinions. Tablica jest na początku pusta ([]) - przy awarii bazy pętla po prostu nic nie wypisze,
w HTML-u pętla foreach w składni alternatywnej (foreach (...): … endforeach;) - przy przeplataniu PHP z HTML-em łatwiej ją czytać niż klamry,
każdy wiersz to <article class="opinion"> - samodzielna wypowiedź klienta; klasa, bo bloków jest kilka (klucz przy R.4.8: identyfikator jest błędem),
<img src="<?= e($opinion['zdjecie']) ?>" alt="klient"> - nazwa pliku z bazy (R.5.5) i tekst alternatywny z arkusza (R.2.8). width i height rezerwują miejsce na zdjęcie, zanim się wczyta.
Podgląd: pięć zdjęć jedno pod drugim - bloki nie mają jeszcze stylu.
Krok 30: Skrypt 1: imię klienta w nagłówku czwartego stopnia
Kryteria: ,
R.5.6 Skrypt 1 dla każdego zwróconego wiersza wyświetla opinię oraz imię pobrane z bazy
R.2.6 W banerze zapisano nagłówek h1: "Hurtownia spożywcza", w bloku głównym zapisano nagłówek h2: "Opinie naszych klientów" oraz przynajmniej jeden h4 (w skrypcie lub HTML), w blokach stopki przynajmniej jeden nagłówek h3 "Współpracują z nami" lub "Nasi top klienci", lub "Skontaktuj się", lub "Autor:" oraz paragraf "telefon 111222333"
ok. 2 min
Polecenie z arkusza
Nagłówek czwartego stopnia, a w nim pobrane z bazy imię klienta
<h4> z imieniem pod cytatem - skrypt 1 wypisuje opinię i imię (R.5.6). Strona ma komplet nagłówków <h1> - <h4> i paragraf z telefonem (R.2.6). Podgląd: Anna, Ewa, Jan, John i Judy.
R.5.8 Skrypt 2 wyświetla zwrócone wiersze jako elementy listy
R.2.7 W drugim bloku stopki umieszczono listę numerowaną, zastosowano znaczniki <ol>, <li> (w skrypcie lub HTML)
ok. 3 min
Polecenie z arkusza
Działanie skryptu 2: Wysyła do bazy zapytanie 1 i wypisuje zwrócone wiersze jako elementy listy
Na górze pliku zapytanie 1 i fetchAll() do $topClients, w liście <ol> pętla foreach z elementami <li> (R.5.8, R.2.7) - na razie imię i nazwisko, oba przez e().
opinie.phpPHPzmienione: 8 linii
<?phpfunctione(string $text): string{returnhtmlspecialchars($text, ENT_QUOTES, 'UTF-8');}$dbError = false;$opinions = [];$topClients = [];try {$pdo = new PDO('mysql:host=localhost;dbname=hurtownia;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);// skrypt 1 - zapytanie 3: opinie klientów złotych i platynowych$opinions = $pdo->query('SELECT zdjecie, imie, opinia FROM klienci JOIN opinie ON klienci.id = opinie.Klienci_id WHERE Typy_id IN (2, 3);') ->fetchAll();// skrypt 2 - zapytanie 1: trzech klientów z największą liczbą punktów$topClients = $pdo->query('SELECT imie, nazwisko, punkty FROM klienci ORDER BY punkty DESC LIMIT 3;') ->fetchAll();} catch (PDOException $exception) {$dbError = true;error_log($exception->getMessage());}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Opinie klientów</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <h1>Hurtownia spożywcza</h1> </header> <main> <h2>Opinie naszych klientów</h2><?phpif ($dbError): ?> <p>Opinie są chwilowo niedostępne, spróbuj ponownie za chwilę.</p><?phpendif; ?><?phpforeach ($opinionsas$opinion): ?> <articleclass="opinion"> <imgsrc="<?= e($opinion['zdjecie']) ?>"alt="klient"width="150"height="200"> <blockquote><?= e($opinion['opinia']) ?></blockquote> <h4><?= e($opinion['imie']) ?></h4> </article><?phpendforeach; ?> </main> <footer> <section> <h3>Współpracują z nami</h3> <ahref="http://sklep.pl/">Sklep 1</a> </section> <section> <h3>Nasi top klienci</h3> <ol><?phpforeach ($topClientsas$client): ?> <li><?= e($client['imie']) ?><?= e($client['nazwisko']) ?></li><?phpendforeach; ?> </ol> </section> <section> <h3>Skontaktuj się</h3> <p>telefon: <ahref="tel:111222333">111222333</a></p> </section> <section> <h3>Autor: Bartosz Bryniarski</h3> </section> </footer></body></html>
Podgląd strony po tym kroku (opinie.php)
Krok 32: Skrypt 2: punkty według wzoru
Kryteria:
R.5.7 Skrypt 2 wyświetla zwrócone wiersze według wzoru: „<imie> <nazwisko>, <punkty> pkt.”, gdzie pola <> są pobrane z bazy
ok. 1 min
Polecenie z arkusza
według wzoru: „<imie><nazwisko>, <punkty> pkt.”, gdzie pola <> są pobrane z bazy
Po nazwisku przecinek, punkty i „pkt.” (R.5.7). Punkty przechodzą przez (int) - liczba całkowita nie zawiera znaczników, więc nie potrzebuje e(). Podgląd: „Jan Nowak, 3305 pkt.”.
opinie.phpPHPzmienione: 1 linia
<?phpfunctione(string $text): string{returnhtmlspecialchars($text, ENT_QUOTES, 'UTF-8');}$dbError = false;$opinions = [];$topClients = [];try {$pdo = new PDO('mysql:host=localhost;dbname=hurtownia;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);// skrypt 1 - zapytanie 3: opinie klientów złotych i platynowych$opinions = $pdo->query('SELECT zdjecie, imie, opinia FROM klienci JOIN opinie ON klienci.id = opinie.Klienci_id WHERE Typy_id IN (2, 3);') ->fetchAll();// skrypt 2 - zapytanie 1: trzech klientów z największą liczbą punktów$topClients = $pdo->query('SELECT imie, nazwisko, punkty FROM klienci ORDER BY punkty DESC LIMIT 3;') ->fetchAll();} catch (PDOException $exception) {$dbError = true;error_log($exception->getMessage());}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Opinie klientów</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <h1>Hurtownia spożywcza</h1> </header> <main> <h2>Opinie naszych klientów</h2><?phpif ($dbError): ?> <p>Opinie są chwilowo niedostępne, spróbuj ponownie za chwilę.</p><?phpendif; ?><?phpforeach ($opinionsas$opinion): ?> <articleclass="opinion"> <imgsrc="<?= e($opinion['zdjecie']) ?>"alt="klient"width="150"height="200"> <blockquote><?= e($opinion['opinia']) ?></blockquote> <h4><?= e($opinion['imie']) ?></h4> </article><?phpendforeach; ?> </main> <footer> <section> <h3>Współpracują z nami</h3> <ahref="http://sklep.pl/">Sklep 1</a> </section> <section> <h3>Nasi top klienci</h3> <ol><?phpforeach ($topClientsas$client): ?> <li><?= e($client['imie']) ?><?= e($client['nazwisko']) ?>, <?= (int) $client['punkty'] ?> pkt.</li><?phpendforeach; ?> </ol> </section> <section> <h3>Skontaktuj się</h3> <p>telefon: <ahref="tel:111222333">111222333</a></p> </section> <section> <h3>Autor: Bartosz Bryniarski</h3> </section> </footer></body></html>
Podgląd strony po tym kroku (opinie.php)
Krok 33: Zamknięcie połączenia z bazą
Kryteria:
R.5.2 Ostatnią operacją na bazie jest jej zamknięcie (zgodne ze składnią)
ok. 2 min
Polecenie z arkusza
Po wykonaniu operacji na bazie danych zamykane jest połączenie z serwerem
PDO nie ma funkcji close - połączenie zamyka się, gdy znika ostatnie odwołanie do obiektu: $pdo = null. Stoi w bloku finally, który wykona się zawsze po try - po udanych zapytaniach i po wyjątku (R.5.2).
Opinie i lista klientów są już w zmiennych $opinions i $topClients, więc HTML wypisuje je po zamknięciu połączenia.
opinie.phpPHPzmienione: 3 linie
<?phpfunctione(string $text): string{returnhtmlspecialchars($text, ENT_QUOTES, 'UTF-8');}$dbError = false;$opinions = [];$topClients = [];$pdo = null;try {$pdo = new PDO('mysql:host=localhost;dbname=hurtownia;charset=utf8mb4', 'root', '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]);// skrypt 1 - zapytanie 3: opinie klientów złotych i platynowych$opinions = $pdo->query('SELECT zdjecie, imie, opinia FROM klienci JOIN opinie ON klienci.id = opinie.Klienci_id WHERE Typy_id IN (2, 3);') ->fetchAll();// skrypt 2 - zapytanie 1: trzech klientów z największą liczbą punktów$topClients = $pdo->query('SELECT imie, nazwisko, punkty FROM klienci ORDER BY punkty DESC LIMIT 3;') ->fetchAll();} catch (PDOException $exception) {$dbError = true;error_log($exception->getMessage());} finally {$pdo = null; // zamknięcie połączenia - ostatnia operacja na bazie}?><!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1"> <title>Opinie klientów</title> <linkrel="stylesheet"href="styl3.css"></head><body> <header> <h1>Hurtownia spożywcza</h1> </header> <main> <h2>Opinie naszych klientów</h2><?phpif ($dbError): ?> <p>Opinie są chwilowo niedostępne, spróbuj ponownie za chwilę.</p><?phpendif; ?><?phpforeach ($opinionsas$opinion): ?> <articleclass="opinion"> <imgsrc="<?= e($opinion['zdjecie']) ?>"alt="klient"width="150"height="200"> <blockquote><?= e($opinion['opinia']) ?></blockquote> <h4><?= e($opinion['imie']) ?></h4> </article><?phpendforeach; ?> </main> <footer> <section> <h3>Współpracują z nami</h3> <ahref="http://sklep.pl/">Sklep 1</a> </section> <section> <h3>Nasi top klienci</h3> <ol><?phpforeach ($topClientsas$client): ?> <li><?= e($client['imie']) ?><?= e($client['nazwisko']) ?>, <?= (int) $client['punkty'] ?> pkt.</li><?phpendforeach; ?> </ol> </section> <section> <h3>Skontaktuj się</h3> <p>telefon: <ahref="tel:111222333">111222333</a></p> </section> <section> <h3>Autor: Bartosz Bryniarski</h3> </section> </footer></body></html>
Kroki 34-37 · po tym etapie masz 36 z 36 kryteriów (pkt)
Krok 34: Bloki opinii: tło, kolor, wymiary, wyśrodkowanie i cień
Kryteria: ,
R.4.8 Ustawiono styl dla bloków opinii (np. klasą, id jest błędem): biały kolor tła, kolor czcionki DimGray, szerokość 60%, wysokość 220px, marginesy zewnętrzne (margin) ustawione są parami na 40px i auto
R.4.9 Ustawiono cień dla bloku opinii bez przesunięcia, rozmyty o 10 px, o rozmiarze 5 px, kolorze DimGray np. box-shadow: 0 0 10px 5px DimGray
ok. 3 min
Polecenie z arkusza
Dla bloków opinii generowanych skryptem: biały kolor tła, kolor czcionki DimGray, szerokość 60%, wysokość 220 px, marginesy zewnętrzne pionowe 40 px, poziome automatycznie wyliczane przez przeglądarkę, cień bez przesunięcia, rozmyty o 10 px, o rozmiarze 5 px, kolorze DimGray
Selektor klasy .opinion. margin: 40px auto - 40 px w pionie, a w poziomie auto stawia blok o szerokości 60% na środku (R.4.8). box-shadow: 0 0 10px 5px - bez przesunięcia, rozmycie 10 px, rozmiar 5 px - w kolorze ze zmiennej --muted, tej samej co tekst (R.4.9).
R.4.10 Ustawiono dla obrazu: opływanie tekstem po prawej jego stronie (np. float: left) i zaokrąglenie rogów o 10px, np. border-radius: 10px;
ok. 2 min
Polecenie z arkusza
Dla selektora obrazu: opływany tekstem po jego prawej stronie, marginesy zewnętrzne 10 px, rogi obrazu zaokrąglone o 10 px
float: left - tekst opływa zdjęcie po prawej, margin: 10px, border-radius: 10px (R.4.10). Tu float jest właściwym narzędziem: arkusz opisuje opływanie tekstem, a do tego służy właśnie ta właściwość. Zdjęcie z marginesami ma 220 px - tyle co blok.
Krok 37: Nagłówek h4: do prawej, margines, rozmiar i pochylenie
Kryteria: , ,
R.4.5 Ustawiono cechy czcionki dla selektora cytatu i h4: pochylenie i rozmiar czcionki 150%
R.4.6 Ustawiono wyrównanie tekstu do środka dla selektora h1 i h2 oraz do prawej strony dla nagłówka h4
R.4.7 Ustawiono marginesy zewnętrzne (margin) 10px dla selektora img oraz prawy (margin- right) 40px dla nagłówka h4 oraz marginesy wewnętrzne (padding) 10px dla banera i cytatu
ok. 2 min
Polecenie z arkusza
Dla selektora nagłówka czwartego stopnia: wyrównanie tekstu do prawej strony, margines zewnętrzny prawy 40 px, czcionka o rozmiarze 150%, pochylona
Selektor znacznika h4. Gotowe są cechy czcionki cytatu i h4 (R.4.5), wyrównanie h1, h2 i h4 (R.4.6) oraz marginesy obrazu, h4, banera i cytatu (R.4.7). Podgląd odpowiada obrazowi 2.
Krok 38 · po tym etapie masz 36 z 36 kryteriów (pkt)
Krok 38: Co jest inaczej i którą wersję wybrać na egzaminie
ok. 3 min
Obie wersje dają komplet 36 punktów. Różnice:
wersja podstawowa
wersja nowoczesna
bloki stopki
cztery <footer> z float: left
jedna <footer> z czterema <section> na siatce
szerokość 25%
width
grid-template-columns: repeat(4, 25%)
blok opinii
<div class="opinion">
<article class="opinion">
kolory
wpisane w każdej regule
zmienne w :root
biblioteka
mysqli (tabela 1 arkusza)
PDO z wyjątkami
gdzie jest kod
dwa bloki PHP w HTML-u
na górze pliku, w HTML-u tylko pętle
odczyt wierszy
mysqli_fetch_row, $row[2]
fetchAll, $opinion['opinia']
wypisywanie danych
echo wprost, htmlspecialchars dopisane w „Dobrych praktykach”
e() od początku
awaria bazy
„Fatal error” ze ścieżką pliku, dopiero potem try / catch
zdanie dla odwiedzającego od początku
zamknięcie bazy
mysqli_close po liście
$pdo = null w finally
Sprawdzone na prawdziwym PHP: skrypt wpisany w treść opinii i atrybut onerror wstrzyknięty przez nazwę zdjęcia wyświetlają się jako tekst, a przy usuniętej bazie strona pokazuje komunikat i całą stopkę.
Na egzaminie wersja podstawowa trzyma się funkcji z tabeli 1 i łatwiej ją napisać bez dokumentacji. Nowoczesna oddziela komunikację z bazą od HTML-u i jest odporna na złe dane i awarię bazy - a klucz przyjmuje obie.
Krok 39 · po tym etapie masz 36 z 36 kryteriów (pkt)
Krok 39: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
UWAGA: po zakończeniu pracy utwórz w folderze z numerem, którym został podpisany arkusz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowałeś poprawność działania witryny. Nagraj płytę z rezultatami pracy.
W przeglądarka.txt nazwa przeglądarki. W folderze: anna.jpg, ewa.jpg, import.jpg, janek.jpg, john.jpg, judy.jpg, kw1.png - kw4.png, kwerendy.txt, opinie.php, przeglądarka.txt i styl3.css. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem zdającego.
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
To jedno z możliwych rozwiązań. Egzaminator ocenia spełnienie kryteriów z klucza odpowiedzi, a nie zgodność z tym kodem - inna, poprawna droga też daje punkty.
Autor rozwiązania: Bartosz Bryniarski. Licencja CC BY-NC 4.0 - kopiowanie i przeróbki do celów niekomercyjnych, z podaniem autora i źródła (link do tej strony) (zasady wykorzystania). Treść arkusza i klucza oceniania pochodzi z CKE.