Projekt: System zarządzania książkami w bibliotece

Cel projektu:

Zbudowanie aplikacji webowej w PHP, która umożliwia zarządzanie książkami w małej bibliotece. Aplikacja ma umożliwiać:

  • dodawanie nowych książek,
  • wyświetlanie listy wszystkich książek,
  • edytowanie danych książek,
  • usuwanie książek,
  • filtrowanie listy książek według autora, roku lub gatunku.

Wymagania funkcjonalne

Tabela books:

KolumnaTyp danychUwagi
idINT AUTO_INCREMENT / SERIALKlucz główny
titleVARCHAR(255)Niepusta
authorVARCHAR(255)Niepusta
genreVARCHAR(100)Np. „kryminał”, „sci-fi”
publish_yearINTRok wydania
created_atDATETIMEAutomatyczna data dodania wpisu

Funkcje aplikacji

  1. Lista książek – tabela z książkami, możliwość filtrowania.
  2. Dodawanie nowej książki – formularz.
  3. Edycja książki – formularz z aktualnymi danymi.
  4. Usuwanie książki – przycisk usuń z potwierdzeniem.
  5. Walidacja danych – nie dopuścić pustych pól, rok w zakresie np. 1500–2025.

Kroki rozwiązania projektu

  • Utwórz bazę danych i tabelę books:
CREATE TABLE books ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255) NOT NULL, author   VARCHAR(255) NOT NULL, genre VARCHAR(100), publish_year INT CHECK (publish_year BETWEEN 1500 AND 2025), created_at DATETIME DEFAULT CURRENT_TIMESTAMP );
  • Skonfiguruj połączenie z bazą danych (plik db.php) :
 <?php 
    $dsn = 'mysql:host=localhost;dbname=biblioteka;charset=utf8mb4'; 
    $user = 'root'; 
    $pass = ''; 
    try {         $pdo = new PDO($dsn, $user, $pass, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ]); 
    } catch (PDOException $e) { 
        die("Błąd połączenia z bazą: " . $e->getMessage()); 
    } 
 ?>
  • Utwórz plik index.php – wyświetlanie i filtrowanie książek
    • Lista książek z możliwością filtrowania (GET).
    • Przycisk „Dodaj”, „Edytuj”, „Usuń”.
  • Utwórz plik add.php – formularz dodawania książki
    • Formularz HTML
    • Obsługa POST z walidacją danych
    • Wstawienie danych do bazy
  • Utwórz plik edit.php – formularz edycji książki
    • Odczyt danych książki po ID
    • Formularz z danymi książki
    • Aktualizacja danych po przesłaniu
  • Utwórz plik delete.php – usuwanie książki po ID z potwierdzeniem
    • Można to zrealizować też przy pomocy GET z linkiem np. delete.php?id=5
  • Walidacja danych po stronie PHP
    • Sprawdzenie pustych pól
    • Sprawdzenie zakresu roku

Przykładowe rozwiązanie: fragment add.php

 <?php    require 'db.php';
     if ($_SERVER["REQUEST_METHOD"] === "POST") {         $title = trim($_POST['title']);
         $author = trim($_POST['author']);
         $genre = $_POST['genre'];
         $year = (int)$_POST['publish_year'];

         $errors = [];

         if (empty($title) || empty($author)) {
             $errors[] = "Tytuł i autor są wymagane.";
         }
         if ($year < 1500 || $year > 2025) {
             $errors[] = "Rok wydania musi być między 1500 a 2025.";
         }

         if (empty($errors)) {
             $stmt = $pdo->prepare("INSERT INTO books (title, author, genre, publish_year) VALUES (?, ?, ?, ?)");
             $stmt->execute([$title, $author, $genre, $year]);
             header("Location: index.php");
             exit;
         }
     }
?>

 <!-- HTML formularz -->
 <form method="POST">
     <input type="text" name="title" placeholder="Tytuł">
     <input type="text" name="author" placeholder="Autor">
     <input type="text" name="genre" placeholder="Gatunek">
     <input type="number" name="publish_year" placeholder="Rok wydania">
     <button type="submit">Dodaj książkę</button>
 </form>

Przykładowy kod pliku index.php:

 <?php
 require 'db.php';

 // Pobierz filtry z URL (GET)
 $author = $_GET['author'] ?? '';
 $genre = $_GET['genre'] ?? '';
 $year = $_GET['year'] ?? '';

 // Buduj zapytanie SQL dynamicznie
 $sql = "SELECT * FROM books WHERE 1=1";
 $params = [];

 if (!empty($author)) {
    $sql .= " AND author LIKE ?";
    $params[] = "%$author%";
 }

 if (!empty($genre)) {
    $sql .= " AND genre LIKE ?";
    $params[] = "%$genre%";
 } 

 if (!empty($year)) {
    $sql .= " AND publish_year = ?";
    $params[] = $year;
 }

 $sql .= " ORDER BY created_at DESC";

 $stmt = $pdo->prepare($sql);
 $stmt->execute($params);
 $books = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>

 <!DOCTYPE html>
 <html lang="pl">
 <head>
    <meta charset="UTF-8">
    <title>Lista książek - Biblioteka</title>
    <style>
        table { border-collapse: collapse; width: 100%; }
        th, td { padding: 8px 12px; border: 1px solid #ccc; }
        form.inline { display: inline; }
    </style>
 </head>
 <body>
    <h1>Lista książek w bibliotece</h1>

    <form method="GET">
        <input type="text" name="author" placeholder="Autor" value="<?= htmlspecialchars($author) ?>">
        <input type="text" name="genre" placeholder="Gatunek" value="<?= htmlspecialchars($genre) ?>">
        <input type="number" name="year" placeholder="Rok" value="<?= htmlspecialchars($year) ?>">
        <button type="submit">Filtruj</button>
        <a href="index.php">Resetuj</a>
    </form>

    <p><a href="add.php">➕ Dodaj nową książkę</a></p>

    <?php if (count($books) === 0): ?>
        <p>Brak książek spełniających kryteria.</p>
    <?php else: ?>
        <table>
            <thead>
                <tr>
                    <th>Tytuł</th>
                    <th>Autor</th>
                    <th>Gatunek</th>
                    <th>Rok</th>
                    <th>Dodano</th>
                    <th>Akcje</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($books as $book): ?>
                <tr>
                    <td><?= htmlspecialchars($book['title']) ?></td>
                    <td><?= htmlspecialchars($book['author']) ?></td>
                    <td><?= htmlspecialchars($book['genre']) ?></td>
                    <td><?= htmlspecialchars($book['publish_year']) ?></td>
                    <td><?= htmlspecialchars($book['created_at']) ?></td>
                    <td>
                        <a href="edit.php?id=<?= $book['id'] ?>">Edytuj</a> |
                        <form action="delete.php" method="POST" class="inline" onsubmit="return confirm('Na pewno usunąć tę książkę?');">
                            <input type="hidden" name="id" value="<?= $book['id'] ?>">
                            <button type="submit">Usuń</button>
                        </form>
                    </td>
                </tr>
                <?php endforeach ?>
            </tbody>
        </table>
    <?php endif; ?>
 </body>
 </html>

Co sprawdza nauczyciel?

  1. Połączenie z bazą danych
  2. Operacje CRUD (4 operacje)
  3. Walidacja danych
  4. Szablon/interfejs graficzny (prostota, funkcjonalność)
  5. Filtrowanie / wyszukiwanie