Skip to content

Rejestr wypożyczeń

This content is not available in your language yet.

Stworzysz Rejestr wypożyczeń - aplikację do zarządzania wypożyczeniami zasobów (np. książki w bibliotece, sprzęt w firmie). System śledzi kto wypożyczył dany przedmiot, kiedy i do kiedy powinien go zwrócić.

Czego się nauczysz?

  • Pracy z datami i terminami zwrotu
  • Obliczania opóźnień i statusów
  • Implementacji przepływu pracy (wypożyczenie → zwrot)
  • Filtrowania danych według statusu
  • Tworzenia raportów i powiadomień

W prawdziwej pracy...

Systemy wypożyczeń są podstawą wielu instytucji - od bibliotek, przez wypożyczalnie sprzętu, po systemy zarządzania zasobami firmowymi. Umiejętność projektowania systemów z kontrolą terminów, statusami i historią transakcji jest fundamentem dla każdego programisty aplikacji logistycznych i inwentaryzacyjnych.

  1. Formularz wypożyczenia Użytkownik podaje dane osoby wypożyczającej, wybiera przedmiot z listy i określa termin zwrotu.

  2. Walidacja danych System sprawdza poprawność wprowadzonych danych - czy termin zwrotu jest późniejszy niż data wypożyczenia, czy przedmiot jest dostępny.

  3. Lista wypożyczeń Wszystkie wypożyczenia są wyświetlane z informacją o statusie (aktywne, zaległe, zwrócone).

  4. Oznaczanie zwrotu Operator może oznaczyć wypożyczenie jako zwrócone, zapisując datę zwrotu.

Przykładowa struktura pliku JSON:

{
"loans": [
{
"id": 1,
"person": "Jan Kowalski",
"contact": "jan@email.pl",
"item": "Władca Pierścieni",
"item_type": "book",
"borrowed_at": "2026-02-01",
"due_at": "2026-02-15",
"returned_at": null,
"notes": "Wydanie kolekcjonerskie",
"created_at": "2026-02-01 10:30:00"
},
{
"id": 2,
"person": "Anna Nowak",
"contact": "anna@email.pl",
"item": "Projektor Epson",
"item_type": "equipment",
"borrowed_at": "2026-02-05",
"due_at": "2026-02-10",
"returned_at": "2026-02-09",
"notes": "",
"created_at": "2026-02-05 14:00:00"
},
{
"id": 3,
"person": "Piotr Wiśniewski",
"contact": "piotr@email.pl",
"item": "1984",
"item_type": "book",
"borrowed_at": "2026-01-20",
"due_at": "2026-02-03",
"returned_at": null,
"notes": "Przedłużenie niemożliwe",
"created_at": "2026-01-20 09:15:00"
}
]
}
  • Directoryrejestr-wypozyczen/
    • index.php (lista wypożyczeń)
    • wypozycz.php (formularz wypożyczenia)
    • zwrot.php (formularz zwrotu)
    • szczegóły.php (podgląd wypożyczenia)
    • zaleglosci.php (lista zaległych - wariant B)
    • Directoryincludes/
      • config.php
      • functions.php
      • validation.php
      • auth.php (wariant C)
    • Directorydata/
      • loans.json
      • items.json (katalog przedmiotów)
      • users.json (wariant C)
    • Directorycss/
      • style.css
    • Directoryjs/
      • validation.js

Wymagane funkcje:

  • Formularz wypożyczenia: osoba, kontakt, przedmiot, termin zwrotu
  • Walidacja PHP (termin zwrotu > data wypożyczenia)
  • Min. 1 walidacja JavaScript
  • Zapis wypożyczeń do pliku JSON
  • Lista wszystkich wypożyczeń
  • Komunikaty błędów i sukcesu

Przykładowy scenariusz:

Użytkownik wpisuje “Jan Kowalski”, wybiera książkę “Władca Pierścieni” i termin zwrotu 15.02.2026. Po zapisie widzi wypożyczenie na liście że statusem “aktywne” i datą zwrotu.

Ocena: 3.0

Walidacja dat:

$borrowedAt = $_POST['borrowed_at'] ?? date('Y-m-d');
$dueAt = $_POST['due_at'] ?? '';
$today = date('Y-m-d');
if (empty($dueAt)) {
$errors[] = "Termin zwrotu jest wymagany";
}
if ($dueAt <= $borrowedAt) {
$errors[] = "Termin zwrotu musi być późniejszy niż data wypożyczenia";
}
// Maksymalny okres wypożyczenia (np. 30 dni)
$maxDue = date('Y-m-d', strtotime($borrowedAt . ' + 30 days'));
if ($dueAt > $maxDue) {
$errors[] = "Maksymalny okres wypożyczenia to 30 dni";
}

Określanie statusu wypożyczenia:

function getLoanStatus(array $loan): string {
// Zwrócone
if (!empty($loan['returned_at'])) {
return 'returned';
}
// Zaległe (po terminie)
$today = date('Y-m-d');
if ($loan['due_at'] < $today) {
return 'overdue';
}
// Aktywne
return 'active';
}
function getStatusInfo(string $status): array {
$statuses = [
'active' => ['label' => 'Aktywne', 'color' => '#27ae60', 'icon' => '📗'],
'overdue' => ['label' => 'Zaległe', 'color' => '#e74c3c', 'icon' => '⚠️'],
'returned' => ['label' => 'Zwrócone', 'color' => '#95a5a6', 'icon' => ''],
];
return $statuses[$status] ?? $statuses['active'];
}

Dodawanie wypożyczenia:

function addLoan(array &$loans, array $data): int {
$newId = empty($loans) ? 1 : max(array_column($loans, 'id')) + 1;
$newLoan = [
'id' => $newId,
'person' => $data['person'],
'contact' => $data['contact'],
'item' => $data['item'],
'item_type' => $data['item_type'] ?? 'book',
'borrowed_at' => $data['borrowed_at'] ?? date('Y-m-d'),
'due_at' => $data['due_at'],
'returned_at' => null,
'notes' => $data['notes'] ?? '',
'created_at' => date('Y-m-d H:i:s'),
];
$loans[] = $newLoan;
return $newId;
}

Oznaczanie zwrotu:

function markAsReturned(array &$loans, int $loanId): bool {
foreach ($loans as &$loan) {
if ($loan['id'] === $loanId) {
$loan['returned_at'] = date('Y-m-d');
return true;
}
}
return false;
}

Filtrowanie wypożyczeń:

function filterLoans(array $loans, string $status): array {
if (empty($status) || $status === 'all') {
return $loans;
}
return array_filter($loans, function($loan) use ($status) {
return getLoanStatus($loan) === $status;
});
}
function getOverdueLoans(array $loans): array {
return filterLoans($loans, 'overdue');
}
function getActiveLoans(array $loans): array {
return filterLoans($loans, 'active');
}

Obliczanie dni do terminu / po terminie:

function getDaysRemaining(array $loan): int {
if (!empty($loan['returned_at'])) {
return 0;
}
$today = new DateTime();
$dueDate = new DateTime($loan['due_at']);
$diff = $today->diff($dueDate);
// Ujemne = po terminie, dodatnie = dni do zwrotu
return $diff->invert ? -$diff->days : $diff->days;
}
function formatDaysRemaining(int $days): string {
if ($days < 0) {
return abs($days) . ' dni po terminie';
} elseif ($days === 0) {
return 'Termin dzisiaj!';
} else {
return $days . ' dni do zwrotu';
}
}

Sortowanie po terminie:

function sortByDueDate(array $loans, string $order = 'asc'): array {
usort($loans, function($a, $b) use ($order) {
$result = strcmp($a['due_at'], $b['due_at']);
return $order === 'desc' ? -$result : $result;
});
return $loans;
}

Statystyki wypożyczeń (wariant C):

function getLoanStatistics(array $loans): array {
$total = count($loans);
$active = count(array_filter($loans, fn($l) => getLoanStatus($l) === 'active'));
$overdue = count(array_filter($loans, fn($l) => getLoanStatus($l) === 'overdue'));
$returned = count(array_filter($loans, fn($l) => getLoanStatus($l) === 'returned'));
// Średni czas wypożyczenia (dla zwróconych)
$returnedLoans = array_filter($loans, fn($l) => !empty($l['returned_at']));
$avgDays = 0;
if (!empty($returnedLoans)) {
$totalDays = 0;
foreach ($returnedLoans as $loan) {
$borrowed = new DateTime($loan['borrowed_at']);
$returned = new DateTime($loan['returned_at']);
$totalDays += $borrowed->diff($returned)->days;
}
$avgDays = round($totalDays / count($returnedLoans), 1);
}
// Najczęściej wypożyczane przedmioty
$itemCounts = array_count_values(array_column($loans, 'item'));
arsort($itemCounts);
$topItems = array_slice($itemCounts, 0, 5, true);
return [
'total' => $total,
'active' => $active,
'overdue' => $overdue,
'returned' => $returned,
'avg_days' => $avgDays,
'top_items' => $topItems,
];
}

Wykorzystaj lekcje!

Cotygodniowe spotkania podczas lekcji to idealny moment, by:

  • Pokazać postępy - nawet małe kroki się liczą
  • Wyjaśnić wątpliwości - pytaj, nie zgaduj
  • Skonsultować rozwiązania - feedback pomoże Ci się rozwijać

Pracuj iteracyjnie - lepiej mieć działający wariant A niż niedokończony C!