🔗 PHP + MySQL - System CRUD

Tworzenie, odczyt, edycja i usuwanie danych

🎯 Czego się nauczysz

CRUD = Create, Read, Update, Delete

  • Łączenie PHP z MySQL przez PDO
  • Wyświetlanie danych z bazy
  • Dodawanie nowych rekordów
  • Edycja istniejących danych
  • Usuwanie rekordów
  • Zabezpieczenia przed SQL Injection

📥 Pobierz bazę danych

Baza ksiazki_db - katalog książek w bibliotece

📁 Struktura projektu

W folderze htdocs (XAMPP) utwórz folder "biblioteka" z plikami:

biblioteka/ ├── config.php (połączenie z bazą) ├── index.php (lista książek) ├── dodaj.php (dodawanie) ├── edytuj.php (edycja) └── usun.php (usuwanie)

🔌 Plik 1: config.php

config.php
<?php $host = 'localhost'; $dbname = 'ksiazki_db'; $username = 'root'; $password = ''; try { $pdo = new PDO( "mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password ); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { die("Błąd połączenia: " . $e->getMessage()); } ?>
Wyjaśnienie: PDO (PHP Data Objects) to bezpieczny sposób łączenia z bazą danych. Używamy prepared statements, które chronią przed SQL Injection.

📖 Plik 2: index.php (Lista)

index.php
<?php require_once 'config.php'; // Pobierz wszystkie książki z bazy $sql = "SELECT * FROM ksiazki ORDER BY tytul"; $stmt = $pdo->query($sql); $ksiazki = $stmt->fetchAll(PDO::FETCH_ASSOC); ?> <!DOCTYPE html> <html lang="pl"> <head> <meta charset="UTF-8"> <title>Biblioteka</title> <style> body { font-family: Arial; max-width: 1200px; margin: 0 auto; padding: 20px; } table { width: 100%; border-collapse: collapse; margin: 20px 0; } th, td { padding: 12px; border: 1px solid #ddd; } th { background: #f093fb; color: white; } .btn { padding: 8px 15px; text-decoration: none; border-radius: 5px; } .btn-add { background: #4caf50; color: white; } .btn-edit { background: #2196f3; color: white; } .btn-delete { background: #f44336; color: white; } </style> </head> <body> <h1>📚 Biblioteka - Katalog Książek</h1> <a href="dodaj.php" class="btn btn-add">➕ Dodaj książkę</a> <table> <tr> <th>ID</th> <th>Tytuł</th> <th>Autor</th> <th>Rok</th> <th>Gatunek</th> <th>Akcje</th> </tr> <?php foreach ($ksiazki as $k): ?> <tr> <td><?php echo htmlspecialchars($k['id']); ?></td> <td><?php echo htmlspecialchars($k['tytul']); ?></td> <td><?php echo htmlspecialchars($k['autor']); ?></td> <td><?php echo htmlspecialchars($k['rok_wydania']); ?></td> <td><?php echo htmlspecialchars($k['gatunek']); ?></td> <td> <a href="edytuj.php?id=<?php echo $k['id']; ?>" class="btn btn-edit">Edytuj</a> <a href="usun.php?id=<?php echo $k['id']; ?>" class="btn btn-delete" onclick="return confirm('Usunąć?')">Usuń</a> </td> </tr> <?php endforeach; ?> </table> </body> </html>
Bezpieczeństwo: Funkcja htmlspecialchars() chroni przed atakami XSS, zamieniając znaki specjalne na bezpieczne encje HTML.

➕ Plik 3: dodaj.php (Dodawanie)

dodaj.php
<?php require_once 'config.php'; $komunikat = ''; $blad = ''; // Sprawdź czy formularz został wysłany if ($_SERVER['REQUEST_METHOD'] === 'POST') { $tytul = trim($_POST['tytul']); $autor = trim($_POST['autor']); $rok = trim($_POST['rok_wydania']); $gatunek = trim($_POST['gatunek']); // Walidacja danych if (empty($tytul) || empty($autor)) { $blad = "Tytuł i autor są wymagane!"; } else { // Prepared statement - bezpieczne zapytanie $sql = "INSERT INTO ksiazki (tytul, autor, rok_wydania, gatunek) VALUES (:tytul, :autor, :rok, :gatunek)"; try { $stmt = $pdo->prepare($sql); $stmt->execute([ ':tytul' => $tytul, ':autor' => $autor, ':rok' => $rok, ':gatunek' => $gatunek ]); $komunikat = "Książka dodana!"; header("refresh:2;url=index.php"); } catch (PDOException $e) { $blad = "Błąd: " . $e->getMessage(); } } } ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Dodaj książkę</title> </head> <body> <h1>Dodaj książkę</h1> <?php if ($komunikat): ?> <div style="background:#d4edda;padding:15px;margin:10px 0;"> <?php echo $komunikat; ?> </div> <?php endif; ?> <?php if ($blad): ?> <div style="background:#f8d7da;padding:15px;margin:10px 0;"> <?php echo $blad; ?> </div> <?php endif; ?> <form method="POST"> <p><label>Tytuł:</label><br> <input type="text" name="tytul" required></p> <p><label>Autor:</label><br> <input type="text" name="autor" required></p> <p><label>Rok wydania:</label><br> <input type="number" name="rok_wydania"></p> <p><label>Gatunek:</label><br> <select name="gatunek"> <option value="">-- Wybierz --</option> <option>Fantasy</option> <option>Kryminał</option> <option>Romans</option> <option>Science Fiction</option> </select></p> <button type="submit">Zapisz</button> </form> <p><a href="index.php">← Powrót</a></p> </body> </html>
Prepared Statements: Parametry :tytul, :autor itd. są bezpiecznie wstawiane przez PDO, co chroni przed SQL Injection!

✏️ Plik 4: edytuj.php (Edycja)

edytuj.php
<?php require_once 'config.php'; if (!isset($_GET['id'])) { header("Location: index.php"); exit(); } $id = (int)$_GET['id']; // Pobierz dane książki $sql = "SELECT * FROM ksiazki WHERE id = :id"; $stmt = $pdo->prepare($sql); $stmt->execute([':id' => $id]); $ksiazka = $stmt->fetch(PDO::FETCH_ASSOC); if (!$ksiazka) { header("Location: index.php"); exit(); } // Obsługa formularza if ($_SERVER['REQUEST_METHOD'] === 'POST') { $sql = "UPDATE ksiazki SET tytul=:tytul, autor=:autor, rok_wydania=:rok, gatunek=:gatunek WHERE id=:id"; $stmt = $pdo->prepare($sql); $stmt->execute([ ':tytul' => $_POST['tytul'], ':autor' => $_POST['autor'], ':rok' => $_POST['rok_wydania'], ':gatunek' => $_POST['gatunek'], ':id' => $id ]); header("Location: index.php"); exit(); } ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Edytuj książkę</title> </head> <body> <h1>Edytuj książkę</h1> <form method="POST"> <p><label>Tytuł:</label><br> <input type="text" name="tytul" value="<?php echo htmlspecialchars($ksiazka['tytul']); ?>"></p> <p><label>Autor:</label><br> <input type="text" name="autor" value="<?php echo htmlspecialchars($ksiazka['autor']); ?>"></p> <p><label>Rok:</label><br> <input type="number" name="rok_wydania" value="<?php echo htmlspecialchars($ksiazka['rok_wydania']); ?>"></p> <p><label>Gatunek:</label><br> <input type="text" name="gatunek" value="<?php echo htmlspecialchars($ksiazka['gatunek']); ?>"></p> <button type="submit">Zapisz zmiany</button> </form> <p><a href="index.php">← Powrót</a></p> </body> </html>

🗑️ Plik 5: usun.php (Usuwanie)

usun.php
<?php require_once 'config.php'; if (!isset($_GET['id'])) { header("Location: index.php"); exit(); } $id = (int)$_GET['id']; $sql = "DELETE FROM ksiazki WHERE id = :id"; $stmt = $pdo->prepare($sql); $stmt->execute([':id' => $id]); header("Location: index.php"); ?>

🔒 Bezpieczeństwo

1. SQL Injection - używaj Prepared Statements

// ❌ ŹLE $sql = "SELECT * FROM ksiazki WHERE id = " . $_GET['id']; // ✅ DOBRZE $sql = "SELECT * FROM ksiazki WHERE id = :id"; $stmt = $pdo->prepare($sql); $stmt->execute([':id' => $_GET['id']]);

2. XSS - zawsze escapuj output

// ❌ ŹLE echo $ksiazka['tytul']; // ✅ DOBRZE echo htmlspecialchars($ksiazka['tytul']);

✏️ Zadania praktyczne

Zadanie 1: Uruchom system (ŁATWY)

  1. Zaimportuj bazę danych ksiazki_db.sql w phpMyAdmin
  2. Stwórz folder "biblioteka" w htdocs
  3. Skopiuj wszystkie 5 plików PHP do folderu
  4. Otwórz http://localhost/biblioteka/
  5. Dodaj 3 nowe książki
  6. Edytuj jedną z nich
  7. Usuń jedną książkę

Zadanie 2: Wyszukiwarka (ŚREDNI)

Dodaj formularz wyszukiwania na stronie głównej:

  • Input tekstowy do wpisania frazy
  • Wyszukiwanie po tytule LUB autorze (użyj LIKE)
  • Przycisk "Wyczyść" wracający do pełnej listy
Wskazówka: WHERE tytul LIKE '%fraza%' OR autor LIKE '%fraza%'

Zadanie 3: Paginacja (ŚREDNI)

Dodaj stronicowanie - 10 książek na stronę:

  • Oblicz liczbę stron: CEIL(liczba_ksiazek / 10)
  • Użyj LIMIT i OFFSET w SQL
  • Linki do poprzedniej/następnej strony
  • Numerowane przyciski stron

Zadanie 4: System logowania (TRUDNY)

Dodaj zabezpieczenie - tylko zalogowani mogą zarządzać:

  • Stwórz tabelę "uzytkownicy" (login, haslo_hash)
  • Plik login.php z formularzem
  • Hashuj hasła: password_hash()
  • Używaj sesji: session_start()
  • Chroń strony: sprawdzaj isset($_SESSION['user_id'])

🎓 Podsumowanie

✅ Czego się nauczyłeś:

  • Łączenia PHP z MySQL przez PDO
  • Wyświetlania danych z bazy (SELECT)
  • Dodawania rekordów (INSERT)
  • Edycji danych (UPDATE)
  • Usuwania rekordów (DELETE)
  • Zabezpieczeń (Prepared Statements, htmlspecialchars)
  • Walidacji danych

Teraz możesz tworzyć dynamiczne aplikacje webowe! 🚀

📚 Dodatkowe zasoby