Cel: Uczeń potrafi utworzyć bazę danych i tabelę do testów CRUD. Polecenie: Utwórz bazę crud_test i tabelę users z polami: id, name, email, age.
CREATE DATABASE crud_test;
USE crud_test;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL,
age INT NOT NULL
);
Baza danych crud_test oraz tabela users zostały utworzone.
2. Połączenie z bazą danych (PDO)
Cel: Uczeń potrafi nawiązać połączenie PHP z MySQL przez PDO. Plik:db.php
ℹ️ Dlaczego PDO, a nie mysqli?
PDO (PHP Data Objects) obsługuje Prepared Statements, które chronią przed SQL Injection.
Jeden plik db.php dołączamy przez require_once do każdego innego pliku —
wtedy zmienna $pdo jest od razu dostępna.
<?php
// db.php – plik konfiguracyjny połączenia z bazą
// Dołączaj go w innych plikach przez: require_once 'db.php';
$host = 'localhost';
$baza = 'crud_test';
$user = 'root';
$haslo = ''; // XAMPP: domyślnie puste
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$baza;charset=$charset";
$opcje = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // rzucaj wyjątki przy błędach
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // wyniki jako tablice asocjacyjne
PDO::ATTR_EMULATE_PREPARES => false, // prawdziwe prepared statements
];
try {
$pdo = new PDO($dsn, $user, $haslo, $opcje);
} catch (PDOException $e) {
die("Błąd połączenia: " . $e->getMessage());
}
?>
Połączenie z bazą danych zostało nawiązane przez PDO.
3. CREATE – Dodawanie danych
Cel: Uczeń potrafi dodać nowy rekord do tabeli users przez Prepared Statement. Polecenie: Utwórz formularz dodający użytkownika (imię, email, wiek).
🛡️ Prepared Statement – dane z formularza ($_POST) nigdy nie trafiają
bezpośrednio do zapytania SQL. PDO traktuje je jako parametry, nie jako kod SQL.
To chroni przed SQL Injection.
Formularz dodawania użytkowników działa poprawnie.
4. READ – Wyświetlanie danych
Cel: Odczytanie wszystkich danych z tabeli i wyświetlenie w tabeli HTML. Plik:index.php
🔒 htmlspecialchars() – każda wartość wyświetlana w HTML powinna być przez nią
przepuszczona. Chroni przed XSS (wstrzykiwaniem kodu HTML/JS przez dane z bazy).
<?php
// index.php
require_once 'db.php';
// query() wystarczy gdy nie ma parametrów od użytkownika
$stmt = $pdo->query("SELECT * FROM users ORDER BY id DESC");
$users = $stmt->fetchAll(); // pobiera wszystkie wiersze naraz
?>
<table class="effect-table">
<tr>
<th>ID</th><th>Imię</th><th>Email</th><th>Wiek</th><th>Akcje</th>
</tr>
<?php foreach ($users as $row): ?>
<tr>
<td><?= htmlspecialchars($row['id']) ?></td>
<td><?= htmlspecialchars($row['name']) ?></td>
<td><?= htmlspecialchars($row['email']) ?></td>
<td><?= htmlspecialchars($row['age']) ?></td>
<td>
<a href="update.php?id=<?= (int)$row['id'] ?>">✏️ Edytuj</a> |
<a href="delete.php?id=<?= (int)$row['id'] ?>">🗑️ Usuń</a>
</td>
</tr>
<?php endforeach; ?>
</table>
ID
Imię
Email
Wiek
Akcje
1
Jan
jan@wp.pl
25
✏️ Edytuj | 🗑️ Usuń
2
Agnieszka
aga@onet.pl
31
✏️ Edytuj | 🗑️ Usuń
5. UPDATE – Edycja danych
Cel: Uczeń potrafi edytować istniejący rekord przez Prepared Statement. Plik:update.php
⚠️ ID z URL zawsze rzutuj na int! $id = (int)$_GET['id']; – nawet jeśli ktoś wpisze w URL złośliwy tekst,
rzutowanie na int zamieni go na 0. Bezpieczne i proste.
<?php
// update.php
require_once 'db.php';
// ID z URL – zawsze rzutujemy na int, nigdy nie ufamy $_GET bezpośrednio
$id = (int)($_GET['id'] ?? 0);
if ($id <= 0) {
die("Nieprawidłowe ID.");
}
// Pobierz aktualny rekord przez Prepared Statement
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
$row = $stmt->fetch();
if (!$row) {
die("Użytkownik nie istnieje.");
}
$sukces = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$age = (int)($_POST['age'] ?? 0);
if ($name !== '' && $email !== '' && $age > 0) {
$stmt = $pdo->prepare(
"UPDATE users SET name = :name, email = :email, age = :age WHERE id = :id"
);
$stmt->execute([':name' => $name, ':email' => $email, ':age' => $age, ':id' => $id]);
$sukces = "✅ Dane zaktualizowane!";
// Odświeżamy $row żeby formularz pokazał nowe dane
$row = ['name' => $name, 'email' => $email, 'age' => $age];
}
}
?>
<?php if ($sukces): ?>
<p><?= htmlspecialchars($sukces) ?> <a href="index.php">Powrót do listy</a></p>
<?php endif; ?>
<form method="POST">
Imię: <input type="text" name="name" value="<?= htmlspecialchars($row['name']) ?>" required><br>
Email: <input type="email" name="email" value="<?= htmlspecialchars($row['email']) ?>" required><br>
Wiek: <input type="number" name="age" value="<?= htmlspecialchars($row['age']) ?>" required min="1"><br>
<button type="submit">Zapisz zmiany</button>
</form>
Dane użytkownika można teraz edytować.
6. DELETE – Usuwanie danych
Cel: Uczeń potrafi usunąć rekord z tabeli. Plik:delete.php
⚠️ Nigdy nie usuwaj przez samo GET bez potwierdzenia!
W prawdziwej aplikacji dodaj potwierdzenie (np. formularz POST z tokenem CSRF).
Tu dla uproszczenia używamy GET z rzutowaniem ID na int.
<?php
// delete.php
require_once 'db.php';
$id = (int)($_GET['id'] ?? 0);
if ($id <= 0) {
die("Nieprawidłowe ID.");
}
$stmt = $pdo->prepare("DELETE FROM users WHERE id = ?");
$stmt->execute([$id]);
echo "🗑️ Użytkownik usunięty. <a href='index.php'>Powrót do listy</a>";
?>