Poniżej znajdziesz kompletne fragmenty rozwiązania. Możesz je skopiować i wkleić do odpowiednich plików serwera.
database.sql — pełne (kliknij by rozwinąć)
-- database.sql (rozwiązanie referencyjne)
CREATE DATABASE IF NOT EXISTS wyprawy_gorskie CHARACTER SET utf8mb4 COLLATE utf8mb4_polish_ci;
USE wyprawy_gorskie;
CREATE TABLE routes (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(150) NOT NULL,
region VARCHAR(100) NOT NULL,
length_km DECIMAL(6,2) NOT NULL,
difficulty ENUM('Łatwa','Średnia','Trudna') NOT NULL DEFAULT 'Średnia',
event_date DATE NOT NULL,
price DECIMAL(8,2) NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE reservations (
id INT AUTO_INCREMENT PRIMARY KEY,
route_id INT NOT NULL,
customer_name VARCHAR(120) NOT NULL,
customer_email VARCHAR(150) NOT NULL,
seats INT NOT NULL DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (route_id) REFERENCES routes(id) ON DELETE CASCADE
);
-- przykładowe dane
INSERT INTO routes (name, region, length_km, difficulty, event_date, price, description) VALUES
('Orlica - Szlak Sokolików','Karkonosze',18.5,'Średnia','2025-07-12',180.00,'Widokowe przejście graniowe.'),
('Perć Najmłodszych','Tatry',8.2,'Trudna','2025-08-02',240.00,'Trudna technicznie, wymagana dobra kondycja.'),
('Wzgórza Bielskie','Beskidy',12.0,'Łatwa','2025-06-20',120.00,'Trasa rekreacyjna dla początkujących.');
config.php
<?php
$DB_HOST = 'localhost';
$DB_USER = 'kursor';
$DB_PASS = 'haslo';
$DB_NAME = 'wyprawy_gorskie';
$mysqli = new mysqli($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME);
if ($mysqli->connect_errno) {
die("Błąd połączenia z bazą: " . $mysqli->connect_error);
}
$mysqli->set_charset("utf8mb4");
?>
index.php (kompaktowe, referencyjne)
<?php
require 'config.php';
// pobierz filtry
$region = $_GET['region'] ?? '';
$difficulty = $_GET['difficulty'] ?? '';
$sql = "SELECT * FROM routes WHERE 1=1";
$params = [];
$types = '';
if ($region !== '') { $sql .= " AND region = ?"; $params[] = $region; $types .= 's'; }
if ($difficulty !== '') { $sql .= " AND difficulty = ?"; $params[] = $difficulty; $types .= 's'; }
$sql .= " ORDER BY event_date ASC";
$stmt = $mysqli->prepare($sql);
if ($params) { $stmt->bind_param($types, ...$params); }
$stmt->execute();
$res = $stmt->get_result();
?>
<!-- HTML część strony -->
<!— wklej tutaj header i style albo użyj jednego pliku —>
<table>
<thead><tr><th>Nazwa</th><th>Region</th><th>Km</th><th>Poziom</th><th>Termin</th><th>Cena</th><th>Akcje</th></tr></thead>
<tbody>
<?php while($row = $res->fetch_assoc()): ?>
<tr>
<td><?=htmlspecialchars($row['name'])?></td>
<td><?=htmlspecialchars($row['region'])?></td>
<td><?=htmlspecialchars($row['length_km'])?></td>
<td><?=htmlspecialchars($row['difficulty'])?></td>
<td><?=htmlspecialchars($row['event_date'])?></td>
<td><?=number_format($row['price'],2,'.',' ')?> zł</td>
<td>
<a href="route_edit.php?id=<?=$row['id']?>">Edytuj</a> |
<a href="route_delete.php?id=<?=$row['id']?>" onclick="return confirm('Usunąć?');">Usuń</a> |
<a href="reserve.php?id=<?=$row['id']?>">Rezerwuj</a>
</td>
</tr>
<?php endwhile; ?>
</tbody>
</table>
route_add.php (referencyjne)
<?php
require 'config.php';
$errors=[];
$name=$region=$length=$difficulty=$event_date=$price=$description='';
if ($_SERVER['REQUEST_METHOD']==='POST') {
$name = trim($_POST['name']);
$region = trim($_POST['region']);
$length = trim($_POST['length']);
$difficulty = $_POST['difficulty'] ?? 'Średnia';
$event_date = $_POST['event_date'] ?? '';
$price = trim($_POST['price']);
$description = trim($_POST['description']);
if ($name==='') $errors[]='Nazwa wymagana';
if ($region==='') $errors[]='Region wymagany';
if (!is_numeric($length) || $length<=0) $errors[]='Długość musi być dodatnia';
if (!in_array($difficulty,['Łatwa','Średnia','Trudna'])) $errors[]='Niepoprawny poziom';
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/',$event_date)) $errors[]='Niepoprawna data';
if (!is_numeric($price) || $price<0) $errors[]='Niepoprawna cena';
if (!$errors) {
$stmt = $mysqli->prepare("INSERT INTO routes (name,region,length_km,difficulty,event_date,price,description) VALUES (?,?,?,?,?,?,?)");
$stmt->bind_param('ssdsdss',$name,$region,$length,$difficulty,$event_date,$price,$description);
if ($stmt->execute()) { header('Location: index.php'); exit; } else { $errors[] = $stmt->error; }
}
}
?>
<!-- HTML formularza tutaj -->
reserve.php (referencyjne)
<?php
require 'config.php';
$id = isset($_GET['id'])?(int)$_GET['id']:0;
if (!$id) { echo "Brak ID"; exit; }
$stmt = $mysqli->prepare("SELECT id,name,event_date,price FROM routes WHERE id=?");
$stmt->bind_param('i',$id); $stmt->execute(); $route = $stmt->get_result()->fetch_assoc();
if (!$route) { echo "Nie znaleziono"; exit; }
$errors=[]; $customer_name=''; $customer_email=''; $seats=1;
if ($_SERVER['REQUEST_METHOD']==='POST') {
$customer_name = trim($_POST['customer_name']);
$customer_email = trim($_POST['customer_email']);
$seats = (int)$_POST['seats'];
if ($customer_name==='') $errors[]='Imię wymagane';
if (!filter_var($customer_email,FILTER_VALIDATE_EMAIL)) $errors[]='Niepoprawny email';
if ($seats<1 || $seats>10) $errors[]='Miejsca 1..10';
if (!$errors) {
$ins = $mysqli->prepare("INSERT INTO reservations (route_id,customer_name,customer_email,seats) VALUES (?,?,?,?)");
$ins->bind_param('issi',$id,$customer_name,$customer_email,$seats);
if ($ins->execute()) {
echo "<div class='note'>Rezerwacja zapisana. Dziękujemy, ".htmlspecialchars($customer_name)."</div>";
exit;
} else { $errors[] = $ins->error; }
}
}
?>
To rozwiązanie jest referencyjne — nauczyciel może je skrócić albo rozszerzyć. W wersji egzaminacyjnej poproś uczniów o zrobienie komentarzy w kodzie i krótkiego raportu.