Zadanie praktyczne INF.03, czerwiec 2025: baza gry w phpMyAdmin, cztery kwerendy SQL, witryna gry.php, arkusz styl.css i skrypty PHP.
Zadanie egzaminacyjne z części praktycznej egzaminu zawodowego INF.03 (Tworzenie i administrowanie stronami i aplikacjami internetowymi oraz bazami danych), sesja czerwiec 2025, numer zadania 01, wersja arkusza SG, kod arkusza INF.03-01-25.06-SG. Czas trwania: 150 minut.
UWAGA: numer, którym został podpisany arkusz egzaminacyjny (PESEL lub w przypadku jego braku numer paszportu) jest w zadaniu nazywany numerem zdającego.
Wykonaj aplikację internetową zawierającą ranking gier komputerowych, wykorzystując edytor grafiki rastrowej, pakiet XAMPP oraz edytor zaznaczający składnię.
Aby wykonać zadanie, należy zalogować się na konto Egzamin bez hasła. Na pulpicie znajduje się archiwum 7z o nazwie pliki1 zabezpieczone hasłem: Gry&KomputErowE
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. Po skończonej pracy wszystkie wyniki należy zapisać w tym folderze. Zaleca się, aby rozpakowane pliki graficzne znajdowały się w tym samym folderze, co pliki źródłowe strony.
Ocenie będzie podlegać 5 rezultatów:
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 folderze z numerem zdającego, powinny znajdować się pliki: Czarodziejka.jpg, gry.php, import.png, kalipso.jpg, katedra.jpg, krokodyl.jpg, kw1.jpg, kw2.jpg, kw3.jpg, kw4.jpg, kwerendy.txt, Mag.jpg, NieznanyLad.jpg, przeglądarka.txt, Persja.jpg, styl.css, WyprawaNaKsiezyc.jpg, zamczysko.jpg, ewentualnie inne przygotowane pliki. Po nagraniu płyty sprawdź poprawność jej odczytu. Opisz płytę numerem zdającego, którym został podpisany arkusz i pozostaw zapakowaną w pudełku na stanowisku wraz z arkuszem egzaminacyjnym.
Treść zadania pochodzi z arkusza CKE (INF.03, czerwiec 2025, zadanie 01). Omówienia i rozwiązania pod każdym rezultatem to opracowanie Prymo – nie są materiałem CKE ani oficjalną wykładnią zasad oceniania.
Baza danych jest zgodna ze strukturą przedstawioną na ilustracji 1.
Ilustracja 1. Baza danych (opis ilustracji – opracowanie Prymo): jedna tabela o nazwie gry z sześcioma polami, gdzie id jest kluczem głównym.
| Pole | Typ |
|---|---|
| id | INTEGER |
| nazwa | VARCHAR(20) |
| opis | TEXT |
| punkty | INTEGER |
| cena | FLOAT |
| zdjecie | VARCHAR(50) |
W tabeli 2 umieszczono wybrane funkcje tekstowe dla bazy danych MariaDB. Za pomocą narzędzia phpMyAdmin wykonaj operacje na bazie danych:
Zapytania do wykonania:
Tabela 2. Wybrane funkcje tekstowe w MariaDB
| Funkcja | Opis |
|---|---|
| LEFT(exp, n) | Dla wyrażenia napisowego exp zwraca n znaków od lewej strony |
| RIGHT(exp, n) | Dla wyrażenia napisowego exp zwraca n znaków od prawej strony |
Krok 1. Baza i import. W phpMyAdmin zakładasz nową bazę gry i wybierasz porównywanie napisów utf8_unicode_ci – dopiero wtedy polskie znaki z pliku baza.sql wczytają się poprawnie. Import robisz w zakładce Import: wskazujesz baza.sql z rozpakowanego archiwum i zatwierdzasz. Po imporcie na liście po lewej stronie musi być widoczna tabela gry z danymi – i to właśnie ma być widać na niekadrowanym zrzucie import.png z paskiem zadań.
Krok 2. Zapytanie 1. Wybierasz trzy kolumny wymienione w treści i nic więcej – żadnej gwiazdki, żadnego opis.
Krok 3. Zapytanie 2. „Pierwsze 100 znaków opisu" to zadanie dla funkcji LEFT z tabeli 2. Warunek WHERE id = 1 ogranicza wynik do jednego wiersza.
Krok 4. Zapytanie 3. „Pięć pierwszych wierszy o najwyższej punktacji" to sortowanie malejąco po punkty i ograniczenie LIMIT 5. Bez ORDER BY samo LIMIT 5 da pięć przypadkowych wierszy.
Krok 5. Zapytanie 4. Dane przepisujesz z pliku rekord.txt. Kolumny id nie wymieniasz w ogóle – klucz główny ma być nadany automatycznie. Cenę i punkty wpisujesz jako liczby, bez „zł".
Za co są punkty:
gry udokumentowany zrzutem import.pngkwerendy.txt zawierający co najmniej jedno zapytanie wynikające z treści zadania-- Krok 1: baza z polskim zestawem znaków
CREATE DATABASE gry DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
USE gry;
-- Import pliku baza.sql wykonujesz w phpMyAdmin (zakładka Import)
-- Zapytanie 1
SELECT id, nazwa, zdjecie FROM gry;
-- Zapytanie 2
SELECT nazwa, LEFT(opis, 100), punkty, cena FROM gry WHERE id = 1;
-- Zapytanie 3
SELECT nazwa, punkty FROM gry ORDER BY punkty DESC LIMIT 5;
-- Zapytanie 4 (dane z pliku rekord.txt, bez kolumny id)
INSERT INTO gry (nazwa, opis, punkty, cena, zdjecie)
VALUES ('Zamczysko', 'Na odludziu stoi opuszczone zamczysko, w którym znajduje się skarb strzeżony przez złowrogie demony i duchy', 200, 50, 'zamczysko.jpg');Omówienie: opracowanie Prymo (do przeglądu).
Ilustracja 2. Witryna internetowa. Kursor na obrazie – widoczny dymek z tekstem, w stopce w formularzu wprowadzono 6
Opis zrzutu (opracowanie Prymo): cała strona ma ciemnofioletowe tło, u góry wyśrodkowany napis „Ranking gier komputerowych". Pod nagłówkiem trzy kolumny obok siebie. W lewej: nagłówek „Top 5 gier w tym miesiącu" i pod nim lista punktowana pięciu gier, przy każdej nazwie liczba punktów w pomarańczowym kółku (Mag 357, Księżniczka Persji 293, Zamczysko 200, Kalipso 125, Wyprawa Na Księżyc 103); niżej nagłówek „Nasz sklep" z odnośnikiem „Tu kupisz gry" oraz nagłówek „Stronę wykonał" z numerem zdającego. Środkowa kolumna ma czarne tło, pionowy pasek przewijania i pokazuje obrazy gier ułożone po dwa obok siebie, każdy z podpisem pod spodem; nad jednym z obrazów stoi kursor i widać dymek z liczbą. W prawej kolumnie nagłówek „Dodaj nową grę", a pod nim cztery etykiety (nazwa, opis, cena, zdjęcie), każda z polem edycyjnym pod nią, i przycisk DODAJ. W stopce pole edycyjne z przyciskiem „Pokaż opis", a pod formularzem nagłówek „Mag, 357 punktów, 150 zł" i akapit z opisem gry.
Przygotowanie grafiki:
Cechy witryny:
Ilustracja 3. Układ bloków (opis ilustracji – opracowanie Prymo): u góry, na całej szerokości, blok nagłówkowy. Pod nim trzy bloki obok siebie: wąski blok sekcji lewej, szeroki blok sekcji środkowej i wąski blok sekcji prawej. Na dole, na całej szerokości, blok stopki.
Zawartość sekcji lewej:
Zawartość sekcji środkowej: Efekt działania skryptu 2
Zawartość sekcji prawej:
Zawartość stopki:
Tabela 3. Semantic Elements in HTML
| Tag | Description |
|---|---|
| <article> | Defines independent, self-contained content |
| <aside> | Defines content aside from the page content |
| <details> | Defines additional details that the user can view or hide |
| <figcaption> | Defines a caption for a <figure> element |
| <figure> | Specifies self-contained content, like illustrations, diagrams, photos, code listings, etc. |
| <footer> | Defines a footer for a document or section |
| <header> | Specifies a header for a document or section |
| <main> | Specifies the main content of a document |
| <mark> | Defines marked/highlighted text |
| <nav> | Defines navigation links |
| <section> | Defines a section in a document |
| <summary> | Defines a visible heading for a <details> element |
| <time> | Defines a date/time |
Krok 1. Grafika. zamczysko.jpg skalujesz w edytorze grafiki rastrowej do szerokości 550 px z zachowaniem proporcji – wysokość wychodzi wtedy 309 px. Plik zapisujesz pod tą samą nazwą, w folderze z numerem zdającego.
Krok 2. Szkielet dokumentu. Deklaracja DOCTYPE dla HTML5, atrybut lang="pl" w znaczniku html, znacznik meta z atrybutem charset ustawionym na utf-8 w sekcji head, tytuł „Gry komputerowe" i odwołanie do styl.css. To cztery osobne, osobno punktowane rzeczy – żadnej nie warto pominąć, bo każda to jedna linijka.
Krok 3. Podział na bloki. Układ z ilustracji 3 składasz z semantycznych znaczników: header, trzy znaczniki section (lewa, środkowa, prawa) i footer. Klasy albo identyfikatory potrzebne będą w rezultacie 4, więc od razu nadaj sekcjom nazwy.
Krok 4. Zawartość sekcji. W lewej: h3, pusta lista ul wypełniana przez skrypt 1, h3, odnośnik do http://sklep.gry.pl, h3 i akapit z numerem zdającego. W środkowej – tylko wynik skryptu 2. W prawej – h3 i formularz z czterema polami z etykietami oraz przyciskiem DODAJ. W stopce – formularz z jednym polem i przyciskiem „Pokaż opis" oraz wynik skryptu 3.
Krok 5. Metoda bezpieczna. „Metoda bezpieczna" w obu formularzach to method="post" – dane nie trafiają wtedy do adresu strony. Brak atrybutu action jest w porządku, bo formularz ma wysyłać dane do tego samego pliku.
Za co są punkty:
zamczysko.jpg o szerokości 550 px i wysokości 309 px (z tolerancją kilku pikseli)spantitle<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="utf-8">
<title>Gry komputerowe</title>
<link rel="stylesheet" href="styl.css">
</head>
<body>
<header><h1>Ranking gier komputerowych</h1></header>
<section id="lewa">
<h3>Top 5 gier w tym miesiącu</h3>
<ul><!-- wypełnia skrypt 1 --></ul>
<h3>Nasz sklep</h3>
<a href="http://sklep.gry.pl">Tu kupisz gry</a>
<h3>Stronę wykonał</h3>
<p>00000000000</p>
</section>
<section id="srodkowa"><!-- wypełnia skrypt 2 --></section>
<section id="prawa">
<h3>Dodaj nową grę</h3>
<form method="post">
<label for="nazwa">nazwa</label><input type="text" name="nazwa" id="nazwa">
<label for="opis">opis</label><input type="text" name="opis" id="opis">
<label for="cena">cena</label><input type="text" name="cena" id="cena">
<label for="zdjecie">zdjęcie</label><input type="text" name="zdjecie" id="zdjecie">
<input type="submit" value="DODAJ">
</form>
</section>
<footer>
<form method="post">
<input type="text" name="id">
<input type="submit" value="Pokaż opis">
</form>
<!-- wypełnia skrypt 3 -->
</footer>
</body>
</html>Omówienie: opracowanie Prymo (do przeglądu).
Ten rezultat nie ma w arkuszu własnego bloku treści – arkusz wymienia go wśród pięciu ocenianych rezultatów („działanie witryny internetowej"), a oceniana jest uruchomiona strona w przeglądarce. Sprawdzane są te wymagania z treści zadania, które widać dopiero po uruchomieniu witryny (przypomnienie – zapisy pochodzą z rezultatu 2 i 4):
Na tym egzaminie obowiązuje jeszcze jedna reguła, którą warto znać: jeżeli witryna nie uruchamia się z powodu błędów PHP, oceniający sprawdza kryteria w kodzie źródłowym strony. Nie jest to zachęta do oddawania niedziałającej strony – ale też jeden błąd w skrypcie nie zeruje całego rezultatu.
Krok 1. Uruchom XAMPP, nie klikaj pliku. Strona gry.php musi działać przez serwer (moduły Apache i MySQL uruchomione, plik w katalogu htdocs). Otwarta z pulpitu podwójnym kliknięciem pokaże surowy kod PHP i wszystkie rezultaty zależne od skryptów przepadną.
Krok 2. Układ trzech kolumn. Trzy sekcje obok siebie ustawiasz w arkuszu stylów – najprościej display: flex na wspólnym rodzicu albo float: left na sekcjach i clear: both na stopce. Oceniany jest efekt na ekranie szerszym niż 800 px; pusty środkowy blok nie jest błędem.
Krok 3. Połączenie z arkuszem stylów. Sprawdź w przeglądarce, czy tło faktycznie zrobiło się fioletowe. Jeżeli nie – zwykle literówka w nazwie pliku albo styl.css leży w innym folderze niż gry.php. Całe formatowanie ma pochodzić z tego jednego pliku, więc nie zostawiaj stylów w atrybucie style ani w sekcji head.
Krok 4. Odnośnik i formularze. Kliknij „Tu kupisz gry" – ma otworzyć się http://sklep.gry.pl (adres nie musi istnieć, liczy się przejście). Wpisz coś w pole w stopce i kliknij przycisk: strona ma się przeładować, a adres nie może pokazać wpisanej wartości – to dowód, że formularz wysyła dane metodą POST.
Za co są punkty:
styl.css, z którego pochodzi całe formatowanieOmówienie: opracowanie Prymo (do przeglądu).
Styl CSS zdefiniowany jest w całości w zewnętrznym pliku o nazwie styl.css
Cechy formatowania CSS, działające na stronie:
Ilustracja 4 (opis ilustracji – opracowanie Prymo): fragment listy punktowanej na fioletowym tle – nazwa gry „Mag", a zaraz za nią liczba 357 na pomarańczowym tle zaokrąglonym do kształtu koła.
Krok 1. Selektor uniwersalny. Krój Garamond i biały kolor czcionki ustawiasz dla wszystkich selektorów, czyli przez *. Kolor przycisku bywa nieodziedziczony – arkusz sam zastrzega, że to nie jest błąd.
Krok 2. Tła i wysokości. Cztery bloki dostają tło Indigo (nagłówek, sekcja lewa, sekcja prawa, stopka), sekcja środkowa czarne. Wysokości: trzy sekcje po 600 px, stopka 150 px. To dwa osobne kryteria, więc warto je wpisać od razu razem.
Krok 3. Układ zależny od szerokości ekranu. Szerokości 20% / 60% / 20% i wyświetlanie obok siebie obowiązują powyżej 800 px, a poniżej sekcje mają stać jedna pod drugą. Najprościej: domyślnie zapisać układ „obok siebie", a w zapytaniu @media all and (max-width: 800px) zmienić szerokość na 100% i wyłączyć opływanie.
Krok 4. Punkty przy nazwie gry. Styl z ilustracji 4 (tło Tomato, border-radius: 50%, padding: 5px) nadajesz klasą – nie identyfikatorem, bo takich oznaczeń jest na stronie pięć, a identyfikator musi być unikalny. Ten sam powód dotyczy bloków gier w sekcji środkowej.
Krok 5. Paski przewijania. „Zawsze widoczne paski przewijania" to overflow: scroll, a nie auto – auto pokaże pasek dopiero wtedy, gdy treść się nie mieści.
Za co są punkty:
* { font-family: Garamond; color: white; }
header { background-color: Indigo; text-align: center; padding: 2px; }
#lewa, #prawa { background-color: Indigo; height: 600px; }
#srodkowa { background-color: black; height: 600px; overflow: scroll; }
footer { background-color: Indigo; height: 150px; }
#lewa, #srodkowa, #prawa { float: left; }
#lewa, #prawa { width: 20%; }
#srodkowa { width: 60%; }
footer { clear: both; }
li { padding: 5px; }
.punkty { background-color: Tomato; border-radius: 50%; padding: 5px; }
.gra { display: inline-block; text-align: center; padding: 3px; }
input { margin: 10px; color: Indigo; }
@media all and (max-width: 800px) {
#lewa, #srodkowa, #prawa { float: none; width: 100%; }
}Omówienie: opracowanie Prymo (do przeglądu).
W tabeli 1 podano wybór funkcji PHP do obsługi bazy danych. Wymagania dotyczące skryptów:
Skrypt 1
Skrypt 2
Skrypt 3 związany z formularzem w stopce
Skrypt 4 związany z formularzem z sekcji prawej
Tabela 1. Wybór funkcji języka PHP do obsługi bazy MySQLi i MariaDB
| Funkcje biblioteki mysqli | Zwracana wartość |
|---|---|
| mysqli_connect(serwer, użytkownik, hasło, nazwa_bazy) | id połączenia lub FALSE, gdy niepowodzenie |
| mysqli_select_db(id_polaczenia, nazwa_bazy) | TRUE/FALSE w zależności od stanu operacji |
| mysqli_error(id_polaczenia) | Tekst komunikatu błędu |
| mysqli_close(id_polaczenia) | TRUE/FALSE w zależności od stanu operacji |
| mysqli_query(id_polaczenia, zapytanie) | Wynik zapytania |
| mysqli_fetch_row(wynik_zapytania) | Tablica numeryczna odpowiadająca wierszowi zapytania |
| mysqli_fetch_array(wynik_zapytania) | Tablica zawierająca kolejny wiersz z podanych w wyniku zapytania lub FALSE, jeżeli nie ma więcej wierszy w wyniku zapytania |
| mysqli_num_rows(wynik_zapytania) | Liczba wierszy w podanym zapytaniu |
| mysqli_num_fields(wynik_zapytania) | Liczba kolumn w podanym zapytaniu |
| isset($zmienna) | TRUE/FALSE w zależności od tego, czy $zmienna istnieje |
Krok 1. Jedno połączenie na całą stronę. mysqli_connect wywołujesz raz, na początku pliku gry.php: serwer localhost, użytkownik root, puste hasło, baza gry. Wynik zapamiętujesz w zmiennej o czytelnej nazwie – nazewnictwo zmiennych jest osobno punktowane.
Krok 2. Skrypt 1 w sekcji lewej. Wysyłasz zapytanie 3 (pięć gier o najwyższej punktacji) i w pętli wypisujesz elementy listy. Liczbę punktów zamykasz w znaczniku span z klasą ze stylu z ilustracji 4 – ten sam element odpowiada za punkt w rezultacie 2 i w rezultacie 4.
Krok 3. Skrypt 2 w sekcji środkowej. Zapytanie 1 zwraca id, nazwa i zdjecie. Dla każdego wiersza wypisujesz blok z obrazem: źródłem jest nazwa pliku z pola zdjecie, tekstem alternatywnym pole nazwa, a atrybutem title – pole id. To właśnie title daje dymek widoczny na ilustracji 2. Pod obrazem akapit z nazwą.
Krok 4. Skrypt 3 w stopce. Działa tylko wtedy, gdy pole formularza zostało wypełnione – stąd sprawdzenie isset i niepusta wartość. Zapytanie 2 modyfikujesz tak, że zamiast id = 1 wstawiasz wartość z formularza. Zwrócony wiersz wypisujesz w nagłówku drugiego stopnia według wzoru z treści, a opis w akapicie. Pamiętaj, że opis jest skracany funkcją LEFT do stu znaków – tak jak w zapytaniu 2.
Krok 5. Skrypt 4 w sekcji prawej. Też uruchamia się warunkowo: tylko gdy wypełnione zostało pole nazwa. Wstawia wiersz z danymi z formularza, a liczbę punktów ustawia na 0. Kolumny id nie podajesz – klucz główny nadaje się sam.
Krok 6. Zamknięcie połączenia. mysqli_close musi być ostatnią operacją na bazie, czyli na końcu pliku, po wszystkich czterech skryptach – a nie po każdym z osobna.
Za co są punkty:
gry<?php
$polaczenie = mysqli_connect("localhost", "root", "", "gry");
if (!$polaczenie) { die("Nie udało się połączyć z bazą danych"); }
// Skrypt 1 – sekcja lewa (zapytanie 3)
$top5 = mysqli_query($polaczenie, "SELECT nazwa, punkty FROM gry ORDER BY punkty DESC LIMIT 5");
while ($wiersz = mysqli_fetch_array($top5)) {
echo "<li>" . $wiersz['nazwa'] . " <span class='punkty'>" . $wiersz['punkty'] . "</span></li>";
}
// Skrypt 2 – sekcja środkowa (zapytanie 1)
$gry = mysqli_query($polaczenie, "SELECT id, nazwa, zdjecie FROM gry");
while ($wiersz = mysqli_fetch_array($gry)) {
echo "<div class='gra'>";
echo "<img src='" . $wiersz['zdjecie'] . "' alt='" . $wiersz['nazwa'] . "' title='" . $wiersz['id'] . "'>";
echo "<p>" . $wiersz['nazwa'] . "</p>";
echo "</div>";
}
// Skrypt 3 – stopka (zapytanie 2 z id z formularza)
if (isset($_POST['id']) && $_POST['id'] != "") {
$szukane = $_POST['id'];
$opis = mysqli_query($polaczenie, "SELECT nazwa, LEFT(opis, 100), punkty, cena FROM gry WHERE id = " . $szukane);
$wiersz = mysqli_fetch_row($opis);
echo "<h2>" . $wiersz[0] . ", " . $wiersz[2] . " punktów, " . $wiersz[3] . " zł</h2>";
echo "<p>" . $wiersz[1] . "</p>";
}
// Skrypt 4 – sekcja prawa (zapytanie 4 z danymi z formularza)
if (isset($_POST['nazwa']) && $_POST['nazwa'] != "") {
$nazwa = $_POST['nazwa'];
$tresc = $_POST['opis'];
$cena = $_POST['cena'];
$zdjecie = $_POST['zdjecie'];
mysqli_query($polaczenie, "INSERT INTO gry (nazwa, opis, punkty, cena, zdjecie) VALUES ('$nazwa', '$tresc', 0, '$cena', '$zdjecie')");
}
mysqli_close($polaczenie);
?>Omówienie: opracowanie Prymo (do przeglądu).