INF.03 styczeń 2026 — portal samochodowy, baza danych i skrypt PHP
Rozbiór arkusza INF.03 ze stycznia 2026: baza samochody, cztery kwerendy SQL, strona index.php, arkusz styl.css i dwa skrypty PHP pobierające dane z bazy. Plan czasowy i rozwiązania do odsłonięcia.
Oryginalny arkusz CKE (PDF)
Pobierz plik źródłowy i rozwiąż go samodzielnie przed sprawdzeniem rozwiązań.
Najtrudniejszy wariant INF.03: strona, która sama pobiera dane z bazy
Styczeń 2026 to pełny zestaw: baza danych z importu, cztery kwerendy SQL, strona w PHP, arkusz stylów i — piąty oceniany rezultat — skrypt połączenia z bazą. Skrypt nie działa tu w przeglądarce, tylko na serwerze: łączy się z MySQL, wysyła zapytanie i wypisuje wyniki wprost do tabel na stronie. Kto ćwiczył wyłącznie JavaScript, ten traci w tym arkuszu dwa rezultaty z pięciu, bo bez działającego skryptu nie zadziała też witryna.
Każdy etap zaczyna się od wymagań arkusza — te widzisz od razu. Rozwiązanie jest schowane pod przyciskiem. Zanim je odsłonisz, spróbuj napisać kod samodzielnie: przeczytanie cudzego rozwiązania nie przygotowuje do egzaminu, na którym trzeba wyprodukować je z głowy w 150 minut, bez internetu i bez podpowiedzi edytora.
📋 Spis treści
1
Metryka arkusza i klucz oceniania
- Kwalifikacja: INF.03 — tworzenie i administrowanie stronami i aplikacjami internetowymi oraz bazami danych
- Sesja: styczeń 2026, zadanie 01, wersja arkusza SG
- Czas: 150 minut, plus 10 minut na zapoznanie się z zadaniem (niewliczane)
- Próg zdania: 75% punktów
- Temat: aplikacja internetowa portalu samochodowego, pakiet XAMPP
- Archiwum: plik
pliki1.7zna pulpicie, hasłoS@mocHody^
Arkusz wymienia pięć rezultatów. To dosłownie lista, po której idzie egzaminator:
- operacje na bazie danych
- zawartość witryny internetowej
- działanie witryny internetowej
- styl CSS witryny internetowej
- skrypt połączenia z bazą
Rezultaty 1, 3 i 5 są ze sobą powiązane: bez zaimportowanej bazy nie zadziała skrypt, a bez skryptu tabele na stronie zostaną puste.
Folder na pulpicie konta Egzamin, nazwany numerem zdającego, a w nim:
a1.jpg obraz z archiwum, wiersz 2 tabeli srodkowej
a2.jpg obraz z archiwum, wiersz 5 tabeli srodkowej
a3.png obraz z archiwum, sekcja prawa
import.jpg zrzut ekranu po imporcie tabel, caly ekran
index.php strona portalu wraz ze skryptami PHP
kw1.png zrzut wyniku zapytania 1
kw2.png zrzut wyniku zapytania 2
kw3.png zrzut wyniku zapytania 3
kw4.png zrzut wyniku zapytania 4
kwerendy.txt tresc czterech zapytan SQL
przegladarka.txt nazwa przegladarki uzytej do testow
styl.css arkusz stylowUwaga na nazwę pliku tekstowego: arkusz żąda nazwy z polskim znakiem,
czyli przeglądarka.txt. Pięć zrzutów ekranu
(import.jpg plus cztery
kw) to punkty do wzięcia
w kilka minut — i najczęściej zapominana część rezultatu za bazę danych.
Format też jest sprawdzany: import w JPEG, kwerendy w PNG.
Czym ten arkusz różni się od stycznia 2024:
tam skrypt był kliencki, w JavaScripcie, i nie było ani jednej kwerendy.
Tutaj strona ma rozszerzenie .php,
a wszystkie dane w tabelach pochodzą z bazy. Do INF.03 trzeba umieć oba
warianty — z arkusza nie da się przewidzieć, który wypadnie.
2
Plan czasowy na 150 minut
Ten egzamin oblewa się przez zegar, nie przez brak wiedzy. Pięć rezultatów waży podobnie, więc porzucony skrypt kosztuje mniej więcej tyle, co porzucone kwerendy. Kolejność ma tu jednak znaczenie większe niż zwykle: baza musi być gotowa przed skryptem, a szkielet HTML przed stylem. Rozkład, który się sprawdza:
| Etap | Czas | Uwagi |
|---|---|---|
| Rozpakowanie archiwum, folder z numerem, start XAMPP | 5 min | Apache i MySQL uruchom od razu, zanim zaczniesz cokolwiek pisać |
| Baza samochody, import baza.sql, zrzut import.jpg | 10 min | bez tego nie ruszysz skryptu, więc idzie pierwsze |
| Cztery kwerendy, kwerendy.txt, cztery zrzuty | 30 min | zrzut rób od razu po wykonaniu kwerendy, nie na końcu |
| index.php — szkielet HTML i obie tabele | 30 min | najpierw statyczny HTML, PHP dokładasz później |
| Skrypt 1 i skrypt 2 w PHP | 30 min | zapytania masz już przetestowane w phpMyAdmin — kopiujesz |
| styl.css | 25 min | idź po kolei po liście z arkusza, punkt po punkcie |
| Testy, przeglądarka.txt, kopiowanie plików, płyta | 20 min | rezerwa, nigdy jej nie tnij |
Dlaczego skrypt przed stylem: styl CSS da się zrobić „na raty" — każda reguła jest niezależna, więc połowa reguł to połowa punktów. Skrypt PHP działa albo nie działa, a kiedy nie działa, ciągnie za sobą rezultat „działanie witryny". Rzecz, która pęka w całości, robisz wcześniej niż tę, która pęka po kawałku.
Zasada, która ratuje egzamin: kiedy etap przekroczy swój limit o więcej niż 5 minut, zostaw go w stanie „działa częściowo" i przejdź dalej. Trzy rezultaty zrobione w 90% dają więcej punktów niż jeden dopieszczony i dwa puste.
3
Operacje na bazie danych
- Utworzyć w phpMyAdmin bazę
samochodyz zestawem polskich znaków, np.utf8_polish_ci. - Zaimportować do niej tabele z pliku
baza.sqlz rozpakowanego archiwum, a po imporcie zrobić niekadrowany zrzut całego ekranu i zapisać go w JPEG jakoimport. - Zapytanie 1: pierwsze 15 rekordów, jedynie pola marka, model, cena, dla pojazdów marki „BM", posortowane malejąco według ceny.
- Zapytanie 2: średnia cena pojazdów oraz najdroższy pojazd dla modelu „meta", z aliasami kolumn „Średnia cena" i „Maksymalna cena".
- Zapytanie 3: z tabeli pojazdy pola marka, model, cena oraz odpowiadające im z tabeli kolory pola nazwa i doplata, dla modelu „alfa" — z użyciem relacji.
- Zapytanie 4: dwa losowe rekordy z tabeli pojazdy, jedynie marka, model i cena.
- Treść zapytań zapisać w
kwerendy.txt, a wyniki udokumentować zrzutami PNG o nazwach kw1–kw4, każdy obejmujący cały ekran z paskiem zadań.
Napisz cztery zapytania samodzielnie, wykonaj je w phpMyAdmin i dopiero potem porównaj z rozwiązaniem.
Pokaż rozwiązanieImport bazy i cztery kwerendy do pliku kwerendy.txt
- W panelu XAMPP uruchom Apache i MySQL, potem otwórz adres localhost/phpmyadmin.
- Zakładka Bazy danych, nazwa
samochody, metoda porównywaniautf8_polish_ci. Kolejność ma znaczenie: kodowanie ustawiasz przed importem, inaczej polskie znaki w danych zamienią się w znaki zapytania. - Zaznacz nową bazę na liście po lewej, wejdź w zakładkę Import, wskaż
baza.sqlz rozpakowanego archiwum i wykonaj. - Zaraz po komunikacie o powodzeniu zrób zrzut całego ekranu (klawisz Print Screen, wklejenie do edytora grafiki) i zapisz jako
import.jpg. Na zrzucie mają być widoczne: komunikat o poprawnym imporcie oraz lista tabel po lewej stronie.
-- Zapytanie 1
SELECT marka, model, cena
FROM pojazdy
WHERE marka = "BM"
ORDER BY cena DESC
LIMIT 15;
-- Zapytanie 2
SELECT AVG(cena) AS "Średnia cena", MAX(cena) AS "Maksymalna cena"
FROM pojazdy
WHERE model = "meta";
-- Zapytanie 3
SELECT pojazdy.marka, pojazdy.model, pojazdy.cena, kolory.nazwa, kolory.doplata
FROM pojazdy
JOIN kolory ON pojazdy.id_koloru = kolory.id
WHERE pojazdy.model = "alfa";
-- Zapytanie 4
SELECT marka, model, cena
FROM pojazdy
ORDER BY RAND()
LIMIT 2;- „Pierwsze 15 rekordów" to
LIMIT 15, a nie ręczne liczenie wierszy na ekranie. Klauzula idzie zawsze na końcu, po sortowaniu. - „Posortowane malejąco" wymaga jawnego
DESC— domyślne sortowanie jest rosnące i egzaminator to sprawdza. - Dwie funkcje agregujące w jednym zapytaniu są całkowicie poprawne:
AVGiMAXzwracają po jednej wartości, więc wynik to jeden wiersz i dwie kolumny. Nie potrzeba tu żadnegoGROUP BY. - Aliasy z polskimi znakami i spacją muszą być w cudzysłowie — bez niego serwer zgłosi błąd składni na spacji.
- „Należy posłużyć się relacją" oznacza złączenie dwóch tabel. Równoważnie zamiast
JOIN ... ONmożesz napisać starszą formę: obie tabele poFROMpo przecinku, a warunek złączenia wWHEREobok warunku na model. Obie wersje są zaliczane. Czego nie zaliczą: dwóch osobnych zapytań albo wypisania kolumn z jednej tabeli. - Losowanie w MySQL i MariaDB to
ORDER BY RAND(). FunkcjaRANDOM()pochodzi z innych silników i tu nie zadziała.
Nazwy kolumn sprawdź w bazie:
relację między tabelami pojazdy i kolory arkusz pokazuje na ilustracji,
a nie w tekście. Po imporcie kliknij tabelę pojazdy
w phpMyAdmin i odczytaj prawdziwą nazwę klucza obcego — w rozwiązaniu wyżej
przyjęto pojazdy.id_koloru
i kolory.id. Jeśli
w Twojej bazie pola nazywają się inaczej, podmień je w zapytaniu 3 i w skrypcie 1.
Gdzie się traci punkty: zrzuty
kadrowane do samego okna przeglądarki — arkusz wprost żąda całego ekranu
z widocznym paskiem zadań. Drugi klasyk to zrzut zrobiony przed
wykonaniem kwerendy, czyli pokazujący samo zapytanie bez wyniku. Trzeci:
pomylone formaty, bo import
ma być w JPEG, a kw1–kw4 w PNG. Czwarty: zapisanie w
kwerendy.txt
tylko trzech zapytań, bo czwarte „przecież widać na zrzucie".
4
Zawartość witryny internetowej
- Jedna strona o nazwie
index.php, w HTML5, z zadeklarowanym polskim językiem zawartości i jawnym kodowaniem polskich znaków. - Tytuł strony „Konfigurator samochodów", prawidłowo podłączony arkusz
styl.css. - Podział na bloki semantycznymi znacznikami HTML5, w układzie zgodnym z ilustracją: nagłówek, nawigacja, blok główny z trzema sekcjami obok siebie, stopka.
- Blok nagłówkowy: nagłówek pierwszego stopnia „Serwis konfiguracji samochodów".
- Blok nawigacyjny: trzy nagłówki drugiego stopnia — „Samochody", „Konfigurator", „Kontakt".
- Sekcja lewa: tabela z czterema kolumnami, wypełniana skryptem 1.
- Sekcja środkowa: tabela z trzema kolumnami i siedmioma wierszami, część komórek scalona. Wiersz 1 — komórki nagłówkowe „Konfiguracja" i „Cena". Wiersz 2 — obraz
a1.jpgz tekstem alternatywnym „Konfiguracja 1". Wiersze 3 i 4 — działanie skryptu 2. Wiersz 5 — obraza2.jpgz tekstem „Konfiguracja 2". Wiersze 6 i 7 — dalszy ciąg skryptu 2. - Sekcja prawa: nagłówek trzeciego stopnia „111 222 444" oraz obraz
a3.pngz tekstem alternatywnym „Samochód". - Stopka: paragraf o treści „Stronę wykonał: " i dalej numer zdającego.
Zbuduj sam szkielet strony razem z obiema tabelami — miejsca na PHP zostaw na razie puste. Potem porównaj.
Pokaż rozwiązanieSzkielet index.php z semantycznymi blokami
Najpierw sam szkielet, bez PHP. Miejsca oznaczone komentarzem wypełnisz skryptami z etapu siódmego.
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="utf-8">
<title>Konfigurator samochodów</title>
<link rel="stylesheet" href="styl.css">
</head>
<body>
<header>
<h1>Serwis konfiguracji samochodów</h1>
</header>
<nav>
<h2>Samochody</h2>
<h2>Konfigurator</h2>
<h2>Kontakt</h2>
</nav>
<main>
<section id="lewa">
<table>
<!-- wiersze generuje skrypt 1 -->
</table>
</section>
<section id="srodkowa">
<table>
<tr>
<th colspan="2">Konfiguracja</th>
<th>Cena</th>
</tr>
<tr>
<td colspan="3"><img src="a1.jpg" alt="Konfiguracja 1"></td>
</tr>
<!-- wiersze 3 i 4: skrypt 2, pierwszy rekord -->
<tr>
<td colspan="3"><img src="a2.jpg" alt="Konfiguracja 2"></td>
</tr>
<!-- wiersze 6 i 7: skrypt 2, drugi rekord -->
</table>
</section>
<section id="prawa">
<h3>111 222 444</h3>
<img src="a3.png" alt="Samochód">
</section>
</main>
<footer>
<p>Stronę wykonał: PESEL</p>
</footer>
</body>
</html>- W miejsce
PESELw stopce wpisujesz swój numer zdającego — ten sam, którym nazwany jest folder i którym opiszesz płytę. lang="pl"realizuje „zadeklarowany polski język zawartości", ameta charset— „jawnie zastosowany właściwy standard kodowania". To dwa osobne punkty, oba w dwóch linijkach.- „Semantyczne znaczniki bloków" to
<header>,<nav>,<main>,<section>i<footer>. Zbudowanie tego samego układu na<div>wygląda identycznie i nie daje punktu —divnie jest znacznikiem semantycznym. - Identyfikatory na sekcjach są konieczne, bo arkusz wymaga stylów działających jedynie na obrazy z bloku środkowego i jedynie na wiersze tabeli z bloku lewego. Bez nich nie da się tego zapisać w CSS.
- Tabela środkowa: siedem znaczników
<tr>w sumie, z czego cztery dołoży PHP. Scalenia: nagłówek „Konfiguracja" obejmuje dwie kolumny, a wiersze z obrazami — wszystkie trzy. Policz kolumny w każdym wierszu: po uwzględnieniucolspanirowspankażdy wiersz musi dawać trzy. - Trzy nagłówki drugiego stopnia w nawigacji to naprawdę
<h2>, a nie odnośniki ani lista. Arkusz mówi „nagłówki drugiego stopnia" i tylko to jest sprawdzane.
Gdzie się traci punkty: teksty
alternatywne przepisane „z głowy" zamiast z arkusza — mają brzmieć
dokładnie „Konfiguracja 1", „Konfiguracja 2" i „Samochód". Dalej:
rozszerzenia obrazów, bo dwa pierwsze to jpg, a trzeci
png. I stopka: arkusz żąda paragrafu, więc treść
musi być w <p>,
a nie luzem w bloku.
5
Działanie witryny internetowej
To rezultat, którego nie ma na osobnej liście — egzaminator po prostu otwiera stronę i patrzy, czy robi to, co opisano. W tym arkuszu „działa" znaczy:
- Strona otwiera się z serwera Apache, a nie z pliku na pulpicie — kod PHP musi zostać wykonany, nie wyświetlony.
- Tabela w sekcji lewej jest wypełniona rekordami z bazy, po jednym wierszu na rekord, z czterema kolumnami.
- W czwartej kolumnie widnieje cena całkowita, czyli suma ceny pojazdu i dopłaty za kolor.
- W tabeli środkowej wiersze 3 i 4 zawierają dane pierwszego wylosowanego pojazdu, a wiersze 6 i 7 — drugiego.
- Po najechaniu kursorem na wiersz tabeli w bloku lewym zmienia się jego kolor tła.
- Wszystkie trzy obrazy się wyświetlają, polskie znaki są poprawne, na stronie nie ma komunikatów o błędach PHP.
Zanim odsłonisz procedurę — spróbuj sam uruchomić swoją stronę przez localhost i wypisać, co poszło nie tak.
Pokaż rozwiązanieUruchomienie przez XAMPP i diagnostyka typowych awarii
- Skopiuj
index.php,styl.cssoraz trzy obrazy do podfolderu w kataloguC:\xampp\htdocs. - W przeglądarce wpisz adres z localhost i nazwą tego podfolderu. Otwarcie pliku dwuklikiem z pulpitu pokaże surowy kod PHP zamiast wyników — Apache musi go najpierw przetworzyć.
- Po zakończeniu pracy skopiuj komplet plików z htdocs do folderu z numerem zdającego na pulpicie. To najczęściej gubiony krok: strona działa, a w oddanym folderze leży stara wersja albo nie ma jej wcale.
| Co widzisz | Przyczyna |
|---|---|
| Na stronie widać kod PHP | plik otwarty z dysku zamiast przez localhost albo zapisany jako .html |
| Pusta tabela w sekcji lewej | zapytanie zwróciło zero wierszy — literówka w nazwie modelu „alfa" albo w nazwie kolumny relacji |
| Komunikat o nieudanym połączeniu | MySQL nie wystartował w panelu XAMPP albo zła nazwa bazy w skrypcie |
| Znaki zapytania zamiast polskich liter w danych z bazy | brak ustawienia kodowania połączenia po stronie skryptu |
| Wiersze tabeli wypadają poza tabelę | blok PHP wstawiony poza znacznikiem tabeli — echo z tr musi być między znacznikami table |
| Nie ma obrazów, jest ikona zepsutego pliku | obrazy nie zostały skopiowane obok index.php albo pomylone rozszerzenie |
Nie masz pewności, czy w ogóle łączysz się z bazą? Zrób w htdocs plik testowy i otwórz go przez localhost — od razu wiadomo, czy problem leży w bazie, czy w HTML-u:
<?php
$polaczenie = mysqli_connect("localhost", "root", "", "samochody");
if (!$polaczenie) {
echo "Brak polaczenia z baza";
} else {
$wynik = mysqli_query($polaczenie, "SELECT COUNT(*) FROM pojazdy");
$wiersz = mysqli_fetch_row($wynik);
echo "Polaczono. Liczba pojazdow: " . $wiersz[0];
mysqli_close($polaczenie);
}
?>Gdzie się traci punkty: praca
wykonana wyłącznie w htdocs
i nieprzeniesiona do folderu z numerem zdającego. Egzaminator ocenia to,
co znajdzie w folderze i na płycie — nie to, co działa na Twoim
stanowisku. Drugi klasyk: strona testowana tylko przy jednym losowaniu.
Odśwież ją kilka razy i sprawdź, czy w wierszach 3, 4, 6 i 7 rzeczywiście
pojawiają się dwa różne pojazdy.
6
Styl CSS witryny
- Domyślnie dla wszystkich selektorów: tekst wyrównany do środka, krój Helvetica, a w razie jego braku sans-serif.
- Wspólne dla nagłówka, nawigacji i stopki: biały kolor czcionki, marginesy wewnętrzne 2 px.
- Dodatkowo: nagłówek i stopka mają tło DarkGreen, nawigacja — ForestGreen.
- Wszystkie bloki sekcji: tło LightGreen, szerokość 33.3%, wysokość 550 px, jedynie górny margines wewnętrzny 10 px, paski przewijania widoczne tylko przy przepełnieniu.
- Nagłówek drugiego stopnia: szerokość 33%, sposób wyświetlania liniowo-blokowy.
- Wspólne dla tabeli, komórki i komórki nagłówkowej: obramowanie linią ciągłą 1 px w kolorze DarkGreen.
- Dodatkowo dla tabeli: szerokość 90%, linie obramowania połączone.
- Jedynie obrazy z bloku środkowego: szerokość 95%, zaokrąglenie rogów 8 px.
- Jedynie wiersze tabeli z bloku lewego: po najechaniu kursorem tło zmienia się na ForestGreen.
- Uwaga z arkusza: style nagłówka drugiego stopnia, tabeli, komórki i komórki nagłówkowej definiujesz wyłącznie selektorem znacznika.
Napisz arkusz, idąc po tej liście od góry, a potem porównaj — zwłaszcza fragment odpowiadający za ustawienie trzech sekcji obok siebie.
Pokaż rozwiązanieKompletny plik styl.css
* {
text-align: center;
font-family: Helvetica, sans-serif;
}
header, nav, footer {
color: white;
padding: 2px;
}
header, footer {
background-color: DarkGreen;
}
nav {
background-color: ForestGreen;
}
section {
background-color: LightGreen;
width: 33.3%;
height: 550px;
padding-top: 10px;
overflow: auto;
float: left;
}
footer {
clear: both;
}
h2 {
width: 33%;
display: inline-block;
}
table, td, th {
border: 1px solid DarkGreen;
}
table {
width: 90%;
border-collapse: collapse;
}
#srodkowa img {
width: 95%;
border-radius: 8px;
}
#lewa tr:hover {
background-color: ForestGreen;
}| Zapis w arkuszu | Co to znaczy w kodzie |
|---|---|
| „domyślnie dla wszystkich selektorów" | selektor uniwersalny, czyli gwiazdka |
| „w przypadku braku, sans-serif" | druga pozycja na liście font-family, po przecinku |
| „jedynie górny margines wewnętrzny 10 px" | padding-top, nie skrócone padding |
| „paski przewijania jedynie przy przepełnieniu" | overflow: auto, a nie scroll |
| „sposób wyświetlania liniowo-blokowy" | display: inline-block — podpowiedź jest w tabeli 2 arkusza |
| „linie obramowania połączone" | border-collapse: collapse |
| „jedynie dla obrazów z bloku środkowego" | selektor potomka: identyfikator sekcji, spacja, img |
Uwaga wprost z arkusza: style
nagłówka drugiego stopnia, tabeli, komórki i komórki nagłówkowej mają być
zdefiniowane wyłącznie przy pomocy selektora tego znacznika.
Zapis nav h2
albo .naglowek
da identyczny wygląd i zero punktów. Zwróć uwagę, że dla obrazów i wierszy
tabeli arkusz każe dokładnie odwrotnie — tam selektor musi
być zawężony do jednej sekcji. Czytaj słowa „wspólne", „dodatkowo"
i „jedynie", bo to one wyznaczają rodzaj selektora.
float: leftna sekcjach — bez tego trzy bloki o szerokości 33.3% ustawią się jeden pod drugim i układ przestanie odpowiadać ilustracji z arkusza. Wymóg układu bloków jest zapisany w części o witrynie, nie w liście CSS, i dlatego łatwo go przeoczyć. Równorzędnie zadziaładisplay: inline-blockna sekcjach.clear: bothna stopce — konsekwencja opływania. Bez tego stopka wjedzie na sekcje albo zniknie za nimi.
7
Skrypt połączenia z bazą
- Oba skrypty napisane w PHP, ze znaczącymi nazwami zmiennych po polsku lub angielsku.
- Połączenie z serwerem na localhost, użytkownik root, bez hasła, baza
samochody. - Skrypt 1: wysyła do bazy zapytanie 3 i wypełnia tabelę w sekcji lewej. W czwartej kolumnie ma się znaleźć cena całkowita — suma ceny z tabeli pojazdy i dopłaty z tabeli kolory. Kolejne rekordy trafiają do kolejnych wierszy tabeli.
- Skrypt 2: wysyła zapytanie 4 i wyświetla pierwszy wylosowany rekord w wierszach 3 i 4 tabeli środkowej, a drugi w wierszach 6 i 7.
- Na końcu połączenie z serwerem zostaje zamknięte.
To najtrudniejszy z pięciu rezultatów. Napisz oba skrypty sam — arkusz daje Ci w tabeli 1 komplet potrzebnych funkcji mysqli, więc niczego nie trzeba pamiętać na wyrywki.
Pokaż rozwiązanieSkrypt 1 — tabela sekcji lewej z ceną całkowitą
Ten blok wstawiasz wewnątrz znacznika tabeli w sekcji lewej — dokładnie w miejsce komentarza ze szkieletu HTML.
<?php
$serwer = "localhost";
$uzytkownik = "root";
$haslo = "";
$baza = "samochody";
$polaczenie = mysqli_connect($serwer, $uzytkownik, $haslo, $baza);
if (!$polaczenie) {
echo "<tr><td colspan='4'>Błąd połączenia z bazą danych</td></tr>";
} else {
mysqli_query($polaczenie, "SET NAMES 'utf8'");
$zapytanie = "SELECT pojazdy.marka, pojazdy.model, pojazdy.cena,
kolory.nazwa, kolory.doplata
FROM pojazdy
JOIN kolory ON pojazdy.id_koloru = kolory.id
WHERE pojazdy.model = 'alfa'";
$wynik = mysqli_query($polaczenie, $zapytanie);
if (!$wynik) {
echo "<tr><td colspan='4'>Błąd zapytania: " . mysqli_error($polaczenie) . "</td></tr>";
} else {
while ($wiersz = mysqli_fetch_row($wynik)) {
$cenaCalkowita = $wiersz[2] + $wiersz[4];
echo "<tr>";
echo "<td>" . $wiersz[0] . "</td>";
echo "<td>" . $wiersz[1] . "</td>";
echo "<td>" . $wiersz[3] . "</td>";
echo "<td>" . $cenaCalkowita . "</td>";
echo "</tr>";
}
}
}
?>- Cztery zmienne z danymi dostępowymi to dokładne odwzorowanie wymagania „localhost, root, bez hasła, baza samochody". Hasło jest pustym łańcuchem — nie pomijaj tego argumentu, bo funkcja z tabeli 1 przyjmuje cztery parametry.
- Sprawdzenie błędu połączenia jest osobno wymienione w arkuszu jako cecha skryptu. Wykrzyknik przed zmienną czyta się „jeśli połączenie się nie udało" — funkcja zwraca fałsz przy niepowodzeniu.
- Ustawienie kodowania połączenia ratuje polskie znaki w danych z bazy. Bez tego nazwy kolorów potrafią się wyświetlić jako znaki zapytania i tracisz punkt za działanie witryny.
- Pętla while z pobraniem wiersza to serce skryptu: funkcja zwraca kolejny wiersz jako tablicę, a gdy wierszy zabraknie — fałsz, co kończy pętlę. Nie trzeba znać liczby rekordów z góry.
- Indeksy tablicy odpowiadają kolejności pól w zapytaniu: 0 to marka, 1 model, 2 cena, 3 nazwa koloru, 4 dopłata. Cena całkowita to suma pól 2 i 4 — dokładnie to, czego żąda arkusz dla czwartej kolumny.
- Znacznik wiersza wypisuje PHP, a nie HTML. Gdyby wiersz stał w kodzie strony, wyświetlałby się także wtedy, gdy baza nic nie zwróci.
Gdzie się traci punkty:
wyliczanie ceny całkowitej w zapytaniu SQL zamiast w skrypcie jest
dopuszczalne, ale wtedy zapytanie przestaje być tym z punktu 3 arkusza —
a arkusz mówi wprost „wysyła do bazy danych zapytanie 3". Bezpieczniej
wysłać zapytanie w tej samej postaci, którą zapisałeś w
kwerendy.txt,
a sumę policzyć w PHP. Drugi klasyk: sklejenie w jednej komórce wszystkich
pól, przez co tabela ma jedną kolumnę zamiast czterech.
Pokaż rozwiązanieSkrypt 2 — dwa losowe rekordy w wierszach 3, 4, 6 i 7
Skrypt 2 rozpada się na dwie części, bo między wierszem 4 a 6 stoi wiersz
z obrazem a2.jpg.
Pierwsza część idzie zaraz po wierszu z obrazem a1, druga po wierszu
z obrazem a2. Poniżej cała tabela sekcji środkowej razem z wstawionym PHP:
<table>
<tr>
<th colspan="2">Konfiguracja</th>
<th>Cena</th>
</tr>
<tr>
<td colspan="3"><img src="a1.jpg" alt="Konfiguracja 1"></td>
</tr>
<?php
if ($polaczenie) {
$losowe = mysqli_query($polaczenie,
"SELECT marka, model, cena FROM pojazdy ORDER BY RAND() LIMIT 2");
$pierwszy = mysqli_fetch_row($losowe);
echo "<tr>";
echo "<td>Marka</td>";
echo "<td>" . $pierwszy[0] . "</td>";
echo "<td rowspan='2'>" . $pierwszy[2] . " zł</td>";
echo "</tr>";
echo "<tr>";
echo "<td>Model</td>";
echo "<td>" . $pierwszy[1] . "</td>";
echo "</tr>";
}
?>
<tr>
<td colspan="3"><img src="a2.jpg" alt="Konfiguracja 2"></td>
</tr>
<?php
if ($polaczenie) {
$drugi = mysqli_fetch_row($losowe);
echo "<tr>";
echo "<td>Marka</td>";
echo "<td>" . $drugi[0] . "</td>";
echo "<td rowspan='2'>" . $drugi[2] . " zł</td>";
echo "</tr>";
echo "<tr>";
echo "<td>Model</td>";
echo "<td>" . $drugi[1] . "</td>";
echo "</tr>";
mysqli_close($polaczenie);
}
?>
</table>- Jedno zapytanie, dwa pobrania. Zapytanie losujące wykonujesz raz, a funkcja pobierająca wiersz zwraca za pierwszym razem pierwszy rekord, za drugim — drugi. Gdybyś wysłał zapytanie dwa razy, losowanie zaczęłoby się od nowa i ten sam pojazd mógłby wypaść dwa razy.
- Zmienna z wynikiem żyje między blokami PHP. Cała strona to jeden skrypt, więc zmienna ustawiona w pierwszym bloku jest dostępna w drugim. Tak samo połączenie otwarte w skrypcie 1 obsługuje skrypt 2 — dlatego zamykasz je dopiero na samym końcu.
- Scalanie komórki z ceną. Cena dotyczy całej konfiguracji, a ta zajmuje dwa wiersze, więc komórka rozciąga się na dwa wiersze. Dzięki temu wiersz z marką ma trzy komórki, a wiersz z modelem dwie — i oba dają w sumie trzy kolumny, zgodnie z opisem tabeli.
| Zapis w arkuszu | Funkcja mysqli |
|---|---|
| „łączy się z serwerem bazodanowym" | mysqli_connect z czterema argumentami |
| sprawdzenie, czy połączenie się udało | warunek na wartości zwróconej przez połączenie, komunikat z mysqli_error |
| „wysyła do bazy danych zapytanie" | mysqli_query |
| „w wierszach wyświetlane są kolejne rekordy" | mysqli_fetch_row w pętli while |
| „na końcu zamykane jest połączenie" | mysqli_close |
Gdzie się traci punkty: zamknięcie połączenia w skrypcie 1. Skrypt 2 pracuje na tym samym połączeniu, więc po wcześniejszym zamknięciu tabela środkowa zostanie pusta i przepadają dwa rezultaty naraz. Drugi błąd to brak zamknięcia w ogóle — arkusz wymienia je jako osobną cechę skryptu. Trzeci: apostrofy i cudzysłowy. Wewnątrz łańcucha otoczonego cudzysłowem wartości atrybutów HTML zapisuj apostrofami, inaczej łańcuch urwie się w połowie i PHP zgłosi błąd składni.
8
Checklista przed oddaniem
- Folder na pulpicie nazwany numerem zdającego, a w nim komplet dwunastu plików z listy.
- Baza
samochodyutworzona z polskim zestawem znaków, tabele zaimportowane zbaza.sql. - Plik
kwerendy.txtzawiera wszystkie cztery zapytania, a nie trzy. - Pięć zrzutów ekranu:
import.jpgw JPEG oraz kw1–kw4 w PNG, wszystkie niekadrowane, z paskiem zadań. - Strona otwiera się przez localhost i nie pokazuje surowego kodu PHP ani komunikatów o błędach.
- Tabela lewa ma cztery kolumny i wypełnia się danymi z bazy, a czwarta kolumna zawiera sumę ceny i dopłaty.
- Tabela środkowa ma dokładnie trzy kolumny i siedem wierszy, po policzeniu scaleń.
- Po odświeżeniu strony w wierszach 3–4 i 6–7 pojawiają się dwa różne, losowe pojazdy.
- Tytuł na karcie przeglądarki brzmi „Konfigurator samochodów", polskie znaki wyświetlają się poprawnie.
- Trzy sekcje stoją obok siebie, a najechanie kursorem na wiersz tabeli w bloku lewym zmienia jego tło.
- W stopce jest paragraf z treścią „Stronę wykonał: " i Twoim numerem zdającego.
- Plik
przeglądarka.txtutworzony i zawiera nazwę użytej przeglądarki. - Pliki przeniesione z
htdocsdo folderu z numerem zdającego w wersji końcowej. - Płyta nagrana, odczyt sprawdzony po nagraniu, opisana numerem zdającego i zapakowana w pudełku.
Przeczytanie rozwiązania to nie to samo, co napisanie go w 150 minut przy włączonym XAMPP-ie i pustym edytorze. Otwórz oryginalny arkusz, ustaw stoper i zrób zadanie od zera — dopiero wynik tej próby pokaże, gdzie naprawdę stoisz.