Przejdź do treści

CRUD — dodawanie, edycja i usuwanie rekordów (PDO)

  • Baza danych
  • poziom: średni
  • aktualizacja: 12 lipca 2026

CRUD (Create, Read, Update, Delete) to szkielet niemal każdej aplikacji — od książki adresowej po panel administracyjny. Ten skrypt pokazuje pełny, bezpieczny obieg: listę rekordów, formularz dodawania i edycji oraz usuwanie, wszystko w jednym pliku.

Operacje zmieniające dane wykonują się wyłącznie metodą POST i są chronione tokenem CSRF, a każde zapytanie z danymi użytkownika korzysta z zapytań przygotowanych.

PHP 168 linii Pobierz .php
<?php
/**
 * CRUD: książka adresowa — skryptyPHP.com
 * Zapisz jako: kontakty.php
 *
 * Najpierw utwórz tabelę (np. w phpMyAdmin):
 *
 *   CREATE TABLE kontakty (
 *       id        INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
 *       imie      VARCHAR(100) NOT NULL,
 *       email     VARCHAR(190) NOT NULL,
 *       telefon   VARCHAR(20)  NOT NULL DEFAULT '',
 *       utworzono DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP
 *   ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_polish_ci;
 */

session_start();
require 'baza.php'; // funkcja polacz_z_baza() — skrypt „Połączenie z bazą (PDO)"

$pdo = polacz_z_baza();

// ── Token CSRF: chroni formularze przed wywołaniem z obcej strony ──
if (empty($_SESSION['csrf'])) {
    $_SESSION['csrf'] = bin2hex(random_bytes(32));
}
function sprawdz_csrf(): void
{
    if (!hash_equals($_SESSION['csrf'], $_POST['csrf'] ?? '')) {
        http_response_code(403);
        exit('Nieprawidłowy token bezpieczeństwa.');
    }
}

$bledy = [];
$edytowany = null;

// ── ZAPIS: dodawanie i aktualizacja (POST) ──────────────────
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['zapisz'])) {
    sprawdz_csrf();

    $id      = (int) ($_POST['id'] ?? 0);
    $imie    = trim($_POST['imie'] ?? '');
    $email   = trim($_POST['email'] ?? '');
    $telefon = trim($_POST['telefon'] ?? '');

    if ($imie === '' || mb_strlen($imie) > 100) {
        $bledy[] = 'Podaj imię i nazwisko (do 100 znaków).';
    }
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $bledy[] = 'Podaj poprawny adres e-mail.';
    }

    if (!$bledy) {
        if ($id > 0) { // aktualizacja
            $stmt = $pdo->prepare(
                'UPDATE kontakty SET imie = ?, email = ?, telefon = ? WHERE id = ?'
            );
            $stmt->execute([$imie, $email, $telefon, $id]);
        } else {       // nowy rekord
            $stmt = $pdo->prepare(
                'INSERT INTO kontakty (imie, email, telefon) VALUES (?, ?, ?)'
            );
            $stmt->execute([$imie, $email, $telefon]);
        }
        header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?')); // wzorzec PRG
        exit;
    }
}

// ── USUWANIE (POST) ─────────────────────────────────────────
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['usun'])) {
    sprawdz_csrf();
    $stmt = $pdo->prepare('DELETE FROM kontakty WHERE id = ?');
    $stmt->execute([(int) $_POST['usun']]);
    header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
    exit;
}

// ── EDYCJA: wczytanie rekordu do formularza (GET) ───────────
if (isset($_GET['edytuj'])) {
    $stmt = $pdo->prepare('SELECT * FROM kontakty WHERE id = ?');
    $stmt->execute([(int) $_GET['edytuj']]);
    $edytowany = $stmt->fetch() ?: null;
}

// ── ODCZYT: lista rekordów ──────────────────────────────────
$kontakty = $pdo->query(
    'SELECT * FROM kontakty ORDER BY imie ASC'
)->fetchAll();
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Książka adresowa</title>
<style>
    body   { font-family: sans-serif; max-width: 760px; margin: 20px auto; }
    table  { border-collapse: collapse; width: 100%; }
    th, td { border: 1px solid #ccc; padding: 8px 10px; text-align: left; }
    th     { background: #f2f2f2; }
    form.wiersz { display: inline; }
    .bledy { color: #b00020; }
    fieldset { margin-bottom: 24px; }
    input  { padding: 6px; margin: 2px 8px 2px 0; }
</style>
</head>
<body>

<h1>Książka adresowa</h1>

<?php if ($bledy): ?>
    <ul class="bledy">
        <?php foreach ($bledy as $blad): ?>
            <li><?= htmlspecialchars($blad) ?></li>
        <?php endforeach; ?>
    </ul>
<?php endif; ?>

<form method="post" action="">
    <fieldset>
        <legend><?= $edytowany ? 'Edytuj kontakt' : 'Dodaj kontakt' ?></legend>
        <input type="hidden" name="csrf" value="<?= htmlspecialchars($_SESSION['csrf']) ?>">
        <input type="hidden" name="id" value="<?= (int) ($edytowany['id'] ?? 0) ?>">

        <input type="text"  name="imie"    placeholder="Imię i nazwisko" required
               value="<?= htmlspecialchars($edytowany['imie'] ?? '') ?>">
        <input type="email" name="email"   placeholder="E-mail" required
               value="<?= htmlspecialchars($edytowany['email'] ?? '') ?>">
        <input type="text"  name="telefon" placeholder="Telefon"
               value="<?= htmlspecialchars($edytowany['telefon'] ?? '') ?>">

        <button type="submit" name="zapisz" value="1">
            <?= $edytowany ? 'Zapisz zmiany' : 'Dodaj' ?>
        </button>
        <?php if ($edytowany): ?>
            <a href="?">anuluj edycję</a>
        <?php endif; ?>
    </fieldset>
</form>

<table>
    <tr><th>Imię i nazwisko</th><th>E-mail</th><th>Telefon</th><th>Akcje</th></tr>
    <?php foreach ($kontakty as $k): ?>
        <tr>
            <td><?= htmlspecialchars($k['imie']) ?></td>
            <td><?= htmlspecialchars($k['email']) ?></td>
            <td><?= htmlspecialchars($k['telefon']) ?></td>
            <td>
                <a href="?edytuj=<?= (int) $k['id'] ?>">edytuj</a>
                <form class="wiersz" method="post" action=""
                      onsubmit="return confirm('Usunąć ten kontakt?');">
                    <input type="hidden" name="csrf"
                           value="<?= htmlspecialchars($_SESSION['csrf']) ?>">
                    <button type="submit" name="usun" value="<?= (int) $k['id'] ?>">
                        usuń
                    </button>
                </form>
            </td>
        </tr>
    <?php endforeach; ?>
    <?php if (!$kontakty): ?>
        <tr><td colspan="4">Brak kontaktów — dodaj pierwszy powyżej.</td></tr>
    <?php endif; ?>
</table>

</body>
</html>

Jak użyć tego skryptu

  1. Utwórz tabelę kontakty — gotowe zapytanie CREATE TABLE znajdziesz w komentarzu na górze skryptu (wklej je np. w phpMyAdmin).
  2. Obok zapisz plik baza.php ze skryptu „Bezpieczne połączenie z bazą MySQL (PDO)" i uzupełnij w nim dane dostępowe.
  3. Zapisz kod jako kontakty.php, wgraj oba pliki na serwer i otwórz w przeglądarce.
  4. Dostosuj kolumny do swoich potrzeb — wystarczy zmienić tabelę, pola formularza i listę kolumn w zapytaniach.

Warto wiedzieć

  • Usuwanie i zapis działają wyłącznie przez POST z tokenem CSRF — dzięki temu obca strona nie wywoła tych operacji za plecami zalogowanego użytkownika.
  • Po każdej operacji zapisu skrypt przekierowuje (wzorzec Post/Redirect/Get), więc odświeżenie strony nie powtórzy operacji.
  • W realnej aplikacji dodaj do tego logowanie (skrypt „Logowanie użytkowników") — panel do edycji danych nie powinien być publiczny.
#crud #pdo #mysql #csrf #panel

Podobne skrypty