W poprzednim materiale nauczyłeś się pobierać dane z bazy używając zapytań SELECT. Teraz czas na operacje, które zmieniają dane:
- INSERT – dodawanie nowych rekordów (np. rejestracja gracza, dodanie posta)
- UPDATE – aktualizacja istniejących danych (np. zmiana poziomu, edycja profilu)
- DELETE – usuwanie rekordów (np. usunięcie konta, skasowanie komentarza)
Te operacje są fundamentem każdej aplikacji:
- Rejestracja użytkownika → INSERT
- Aktualizacja avatara → UPDATE
- Usunięcie spamu → DELETE
- System komentarzy → INSERT + UPDATE + DELETE
UWAGA: Operacje zmieniające dane są nieodwracalne! Zawsze używaj prepared statements i walidacji danych.
Będziemy pracować na bazie gaming_hub z poprzedniego materiału. Upewnij się, że masz utworzoną tabelę players
UWAGA: Przedstawione poniżej przykłady nie są zabezpieczone przed odświeżaniem strony (F5) lub ponownym kliknięciem przycisku zmieniającego dane. Każde odświeżenie strony będzie powodowało ponowne wykonanie operacji na bazie. Jak to zrobić opiszę na końcu materiału.
INSERT – Dodawanie nowych rekordów
Przykład 1: Rejestracja gracza (formularz POST)
MySQLi obiektowo:
<?php
mysqli_report(MYSQLI_REPORT_OFF);
$db = @new mysqli('localhost', 'root', '', 'gaming_hub');
if ($db->connect_error) {
die('Błąd połączenia');
}
$db->set_charset('utf8mb4');
$errors = [];
$success = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Pobieramy i czyszczenie dane z formularza
$username = trim($_POST['username'] ?? '');
$email = trim($_POST['email'] ?? '');
$password = $_POST['password'] ?? '';
$password_confirm = $_POST['password_confirm'] ?? '';
// Walidacja danych
if (empty($username)) {
$errors[] = "Nick jest wymagany";
} elseif (strlen($username) < 3) {
$errors[] = "Nick musi mieć minimum 3 znaki";
} elseif (strlen($username) > 50) {
$errors[] = "Nick może mieć maksymalnie 50 znaków";
} elseif (!preg_match('/^[a-zA-Z0-9_]+$/', $username)) {
$errors[] = "Nick może zawierać tylko litery, cyfry i podkreślnik";
}
if (empty($email)) {
$errors[] = "Email jest wymagany";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "Nieprawidłowy format email";
}
if (empty($password)) {
$errors[] = "Hasło jest wymagane";
} elseif (strlen($password) < 8) {
$errors[] = "Hasło musi mieć minimum 8 znaków";
}
if ($password !== $password_confirm) {
$errors[] = "Hasła nie są identyczne";
}
// Jeśli brak błędów walidacji - sprawdzamy czy nick/email już istnieją
if (empty($errors)) {
// BEZPIECZNE - sprawdzamy czy username już istnieje
$stmt = $db->prepare("SELECT id FROM players WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
$errors[] = "Nick '{$username}' jest już zajęty";
}
$stmt->close();
// BEZPIECZNE - sprawdzamy czy email już istnieje
$stmt = $db->prepare("SELECT id FROM players WHERE email = ?");
$stmt->bind_param("s", $email);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
$errors[] = "Email '{$email}' jest już zarejestrowany";
}
$stmt->close();
}
// Jeśli wszystko OK - dodajemy gracza do bazy
if (empty($errors)) {
// Hashowanie hasła (NIGDY nie zapisuj hasła w plain text!)
$password_hash = password_hash($password, PASSWORD_DEFAULT);
// BEZPIECZNE - INSERT z prepared statement
$stmt = $db->prepare("INSERT INTO players (username, email, password, created_at) VALUES (?, ?, ?, NOW())");
$stmt->bind_param("sss", $username, $email, $password_hash);
if ($stmt->execute()) {
// Pobieramy ID dodanego gracza
$new_player_id = $stmt->insert_id;
// Sprawdzamy ile wierszy zostało dodanych
$affected_rows = $stmt->affected_rows;
$success = true;
$success_message = "Gracz '{$username}' został zarejestrowany! ID: {$new_player_id}";
// Możemy od razu zalogować użytkownika
// session_start();
// $_SESSION['user_id'] = $new_player_id;
// $_SESSION['username'] = $username;
} else {
$errors[] = "Wystąpił błąd podczas rejestracji: {$stmt->error}";
}
$stmt->close();
}
}
$db->close();
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Rejestracja gracza</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.container {
background: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
width: 100%;
max-width: 500px;
}
h1 {
margin-bottom: 30px;
color: #333;
text-align: center;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
color: #555;
font-weight: 500;
}
input {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
transition: border-color 0.3s;
}
input:focus {
outline: none;
border-color: #667eea;
}
button {
width: 100%;
padding: 12px;
background: #667eea;
color: white;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
transition: background 0.3s;
}
button:hover {
background: #764ba2;
}
.error {
background: #f8d7da;
color: #721c24;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #f5c6cb;
}
.error ul {
margin-left: 20px;
}
.success {
background: #d4edda;
color: #155724;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #c3e6cb;
text-align: center;
}
.info {
background: #d1ecf1;
color: #0c5460;
padding: 10px;
border-radius: 5px;
margin-top: 15px;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container">
<h1>Rejestracja Gracza</h1>
<?php if ($success): ?>
<div class="success">
<?= htmlspecialchars($success_message) ?>
<br><br>
<a href="profil.php?id=<?= $new_player_id ?>">Zobacz profil</a> |
<a href="lista_graczy.php">Lista graczy</a>
</div>
<?php endif; ?>
<?php if (!empty($errors)): ?>
<div class="error">
<strong>Błędy walidacji:</strong>
<ul>
<?php foreach ($errors as $error): ?>
<li><?= htmlspecialchars($error) ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label>Nick gracza:</label>
<input type="text" name="username"
value="<?= htmlspecialchars($_POST['username'] ?? '') ?>"
placeholder="np. ProGamer123"
required>
</div>
<div class="form-group">
<label>Email:</label>
<input type="email" name="email"
value="<?= htmlspecialchars($_POST['email'] ?? '') ?>"
placeholder="twoj@email.com"
required>
</div>
<div class="form-group">
<label>Hasło:</label>
<input type="password" name="password"
placeholder="Min. 8 znaków"
required>
</div>
<div class="form-group">
<label>Powtórz hasło:</label>
<input type="password" name="password_confirm"
placeholder="Powtórz hasło"
required>
</div>
<button type="submit">Zarejestruj się</button>
<div class="info">
<strong>Wymagania:</strong><br>
• Nick: 3-50 znaków (litery, cyfry, podkreślnik)<br>
• Hasło: minimum 8 znaków<br>
• Poprawny format email
</div>
</form>
</div>
</body>
</html>
PDO:
<?php
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=gaming_hub;charset=utf8mb4',
'root',
'',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
$errors = [];
$success = false;
// PROFESJONALNE - sprawdzamy metodę HTTP
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Pobieramy i czyszczenie dane z formularza
$username = trim($_POST['username'] ?? '');
$email = trim($_POST['email'] ?? '');
$password = $_POST['password'] ?? '';
$password_confirm = $_POST['password_confirm'] ?? '';
// Walidacja danych
if (empty($username)) {
$errors[] = "Nick jest wymagany";
} elseif (strlen($username) < 3) {
$errors[] = "Nick musi mieć minimum 3 znaki";
} elseif (strlen($username) > 50) {
$errors[] = "Nick może mieć maksymalnie 50 znaków";
} elseif (!preg_match('/^[a-zA-Z0-9_]+$/', $username)) {
$errors[] = "Nick może zawierać tylko litery, cyfry i podkreślnik";
}
if (empty($email)) {
$errors[] = "Email jest wymagany";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "Nieprawidłowy format email";
}
if (empty($password)) {
$errors[] = "Hasło jest wymagane";
} elseif (strlen($password) < 8) {
$errors[] = "Hasło musi mieć minimum 8 znaków";
}
if ($password !== $password_confirm) {
$errors[] = "Hasła nie są identyczne";
}
// Jeśli brak błędów walidacji - sprawdzamy czy nick/email już istnieją
if (empty($errors)) {
// BEZPIECZNE - sprawdzamy czy username już istnieje
$stmt = $pdo->prepare("SELECT id FROM players WHERE username = :username");
$stmt->execute(['username' => $username]);
if ($stmt->fetch()) {
$errors[] = "Nick '{$username}' jest już zajęty";
}
// BEZPIECZNE - sprawdzamy czy email już istnieje
$stmt = $pdo->prepare("SELECT id FROM players WHERE email = :email");
$stmt->execute(['email' => $email]);
if ($stmt->fetch()) {
$errors[] = "Email '{$email}' jest już zarejestrowany";
}
}
// Jeśli wszystko OK - dodajemy gracza do bazy
if (empty($errors)) {
// Hashowanie hasła (NIGDY nie zapisuj hasła w plain text!)
$password_hash = password_hash($password, PASSWORD_DEFAULT);
// BEZPIECZNE - INSERT z prepared statement
$stmt = $pdo->prepare("INSERT INTO players (username, email, password, created_at) VALUES (:username, :email, :password, NOW())");
if ($stmt->execute([
'username' => $username,
'email' => $email,
'password' => $password_hash
])) {
// Pobieramy ID dodanego gracza
$new_player_id = $pdo->lastInsertId();
// Sprawdzamy ile wierszy zostało dodanych
$affected_rows = $stmt->rowCount();
$success = true;
$success_message = "Gracz '{$username}' został zarejestrowany! ID: {$new_player_id}";
// Możemy od razu zalogować użytkownika
// session_start();
// $_SESSION['user_id'] = $new_player_id;
// $_SESSION['username'] = $username;
}
}
}
} catch (PDOException $e) {
error_log("DB Error: {$e->getMessage()}");
$errors[] = "Wystąpił błąd podczas rejestracji. Spróbuj ponownie.";
}
$pdo = null;
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Rejestracja gracza</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.container {
background: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
width: 100%;
max-width: 500px;
}
h1 {
margin-bottom: 30px;
color: #333;
text-align: center;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
color: #555;
font-weight: 500;
}
input {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
transition: border-color 0.3s;
}
input:focus {
outline: none;
border-color: #667eea;
}
button {
width: 100%;
padding: 12px;
background: #667eea;
color: white;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
transition: background 0.3s;
}
button:hover {
background: #764ba2;
}
.error {
background: #f8d7da;
color: #721c24;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #f5c6cb;
}
.error ul {
margin-left: 20px;
}
.success {
background: #d4edda;
color: #155724;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #c3e6cb;
text-align: center;
}
.info {
background: #d1ecf1;
color: #0c5460;
padding: 10px;
border-radius: 5px;
margin-top: 15px;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container">
<h1>Rejestracja Gracza</h1>
<?php if ($success): ?>
<div class="success">
<?= htmlspecialchars($success_message) ?>
<br><br>
<a href="profil.php?id=<?= $new_player_id ?>">Zobacz profil</a> |
<a href="lista_graczy.php">Lista graczy</a>
</div>
<?php endif; ?>
<?php if (!empty($errors)): ?>
<div class="error">
<strong>Błędy walidacji:</strong>
<ul>
<?php foreach ($errors as $error): ?>
<li><?= htmlspecialchars($error) ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label>Nick gracza:</label>
<input type="text" name="username"
value="<?= htmlspecialchars($_POST['username'] ?? '') ?>"
placeholder="np. ProGamer123"
required>
</div>
<div class="form-group">
<label>Email:</label>
<input type="email" name="email"
value="<?= htmlspecialchars($_POST['email'] ?? '') ?>"
placeholder="twoj@email.com"
required>
</div>
<div class="form-group">
<label>Hasło:</label>
<input type="password" name="password"
placeholder="Min. 8 znaków"
required>
</div>
<div class="form-group">
<label>Powtórz hasło:</label>
<input type="password" name="password_confirm"
placeholder="Powtórz hasło"
required>
</div>
<button type="submit">Zarejestruj się</button>
<div class="info">
<strong>Wymagania:</strong><br>
• Nick: 3-50 znaków (litery, cyfry, podkreślnik)<br>
• Hasło: minimum 8 znaków<br>
• Poprawny format email
</div>
</form>
</div>
</body>
</html>
Sprawdzanie wyniku operacji INSERT
Metody sprawdzania dla MySQLi:
// 1. Pobierz ID ostatnio dodanego rekordu
$new_id = $stmt->insert_id; // Obiektowo
$new_id = mysqli_insert_id($db); // Proceduralnie
// 2. Sprawdź ile wierszy zostało dodanych
$affected_rows = $stmt->affected_rows; // Obiektowo
$affected_rows = mysqli_affected_rows($db); // Proceduralnie
// 3. Sprawdź czy zapytanie się wykonało
if ($stmt->execute()) {
echo "Sukces!";
} else {
echo "Błąd: {$stmt->error}";
}
Metody sprawdzania dla PDO:
// 1. Pobierz ID ostatnio dodanego rekordu
$new_id = $pdo->lastInsertId();
// 2. Sprawdź ile wierszy zostało dodanych
$affected_rows = $stmt->rowCount();
// 3. Sprawdź czy zapytanie się wykonało
if ($stmt->execute()) {
echo "Sukces!";
} else {
echo "Błąd!";
}
// 4. Obsługa wyjątków (try-catch)
try {
$stmt->execute();
echo "Sukces!";
} catch (PDOException $e) {
echo "Błąd: {$e->getMessage()}";
}
Przykład 2: Dodawanie wielu graczy naraz (batch INSERT)
MySQLi obiektowo:
<?php
mysqli_report(MYSQLI_REPORT_OFF);
$db = @new mysqli('localhost', 'root', '', 'gaming_hub');
if ($db->connect_error) {
die('Błąd połączenia');
}
$db->set_charset('utf8mb4');
// Tablica graczy do dodania
$gracze = [
['username' => 'TestPlayer1', 'email' => 'test1@example.com', 'level' => 5],
['username' => 'TestPlayer2', 'email' => 'test2@example.com', 'level' => 10],
['username' => 'TestPlayer3', 'email' => 'test3@example.com', 'level' => 15]
];
// BEZPIECZNE - przygotowanie zapytania raz
$stmt = $db->prepare("INSERT INTO players (username, email, level, created_at) VALUES (?, ?, ?, NOW())");
$dodano = 0;
$bledy = [];
foreach ($gracze as $gracz) {
// Bindowanie parametrów
$stmt->bind_param("ssi", $gracz['username'], $gracz['email'], $gracz['level']);
if ($stmt->execute()) {
$dodano++;
// Możesz pobrać ID każdego dodanego gracza
$last_id = $stmt->insert_id;
echo "Dodano: {$gracz['username']} (ID: {$last_id})<br>";
} else {
$bledy[] = "Błąd dla {$gracz['username']}: {$stmt->error}";
}
}
echo "<br><strong>Podsumowanie:</strong><br>";
echo "Dodano: {$dodano} graczy<br>";
echo "Błędów: " . count($bledy) . "<br>";
if (!empty($bledy)) {
echo "<br><strong>Szczegóły błędów:</strong><br>";
foreach ($bledy as $blad) {
echo "{$blad}<br>";
}
}
$stmt->close();
$db->close();
?>
PDO:
<?php
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=gaming_hub;charset=utf8mb4',
'root',
'',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
// Tablica graczy do dodania
$gracze = [
['username' => 'TestPlayer1', 'email' => 'test1@example.com', 'level' => 5],
['username' => 'TestPlayer2', 'email' => 'test2@example.com', 'level' => 10],
['username' => 'TestPlayer3', 'email' => 'test3@example.com', 'level' => 15]
];
// BEZPIECZNE - przygotowanie zapytania raz
$stmt = $pdo->prepare("INSERT INTO players (username, email, level, created_at) VALUES (:username, :email, :level, NOW())");
$dodano = 0;
$bledy = [];
foreach ($gracze as $gracz) {
try {
$stmt->execute($gracz);
$dodano++;
// Możesz pobrać ID każdego dodanego gracza
$last_id = $pdo->lastInsertId();
echo "Dodano: {$gracz['username']} (ID: {$last_id})<br>";
} catch (PDOException $e) {
$bledy[] = "Błąd dla {$gracz['username']}: {$e->getMessage()}";
}
}
echo "<br><strong>Podsumowanie:</strong><br>";
echo "Dodano: {$dodano} graczy<br>";
echo "Błędów: " . count($bledy) . "<br>";
if (!empty($bledy)) {
echo "<br><strong>Szczegóły błędów:</strong><br>";
foreach ($bledy as $blad) {
echo "{$blad}<br>";
}
}
} catch (PDOException $e) {
error_log("DB Error: {$e->getMessage()}");
die('Błąd bazy danych');
}
$pdo = null;
?>
UPDATE – Aktualizacja istniejących rekordów
Przykład 3: Edycja profilu gracza (formularz POST)
MySQLi obiektowo:
<?php
mysqli_report(MYSQLI_REPORT_OFF);
$db = @new mysqli('localhost', 'root', '', 'gaming_hub');
if ($db->connect_error) {
die('Błąd połączenia');
}
$db->set_charset('utf8mb4');
$errors = [];
$success = false;
$gracz = null;
// Pobieramy ID gracza z URL
$player_id = (int)($_GET['id'] ?? 0);
if ($player_id <= 0) {
die('Nieprawidłowe ID gracza');
}
// Pobieramy dane gracza do wyświetlenia w formularzu
$stmt = $db->prepare("SELECT * FROM players WHERE id = ?");
$stmt->bind_param("i", $player_id);
$stmt->execute();
$wynik = $stmt->get_result();
$gracz = $wynik->fetch_assoc();
$stmt->close();
if (!$gracz) {
die('Nie znaleziono gracza o ID: ' . $player_id);
}
// PROFESJONALNE - sprawdzamy metodę HTTP
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Pobieramy dane z formularza
$email = trim($_POST['email'] ?? '');
$level = (int)($_POST['level'] ?? 1);
$coins = (int)($_POST['coins'] ?? 0);
$rank_name = $_POST['rank_name'] ?? 'Bronze';
// Walidacja danych
if (empty($email)) {
$errors[] = "Email jest wymagany";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "Nieprawidłowy format email";
}
if ($level < 1 || $level > 100) {
$errors[] = "Poziom musi być między 1 a 100";
}
if ($coins < 0) {
$errors[] = "Coins nie może być ujemny";
}
$allowed_ranks = ['Bronze', 'Silver', 'Gold', 'Platinum', 'Diamond', 'Master', 'Grandmaster'];
if (!in_array($rank_name, $allowed_ranks)) {
$errors[] = "Nieprawidłowa ranga";
}
// Sprawdzamy czy email nie jest już używany przez innego gracza
if (empty($errors)) {
$stmt = $db->prepare("SELECT id FROM players WHERE email = ? AND id != ?");
$stmt->bind_param("si", $email, $player_id);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
$errors[] = "Email '{$email}' jest już używany przez innego gracza";
}
$stmt->close();
}
// Jeśli brak błędów - aktualizujemy dane
if (empty($errors)) {
// BEZPIECZNE - UPDATE z prepared statement
$stmt = $db->prepare("UPDATE players SET email = ?, level = ?, coins = ?, rank_name = ?, updated_at = NOW() WHERE id = ?");
$stmt->bind_param("siisi", $email, $level, $coins, $rank_name, $player_id);
if ($stmt->execute()) {
// Sprawdzamy ile wierszy zostało zaktualizowanych
$affected_rows = $stmt->affected_rows;
if ($affected_rows > 0) {
$success = true;
$success_message = "Profil gracza '{$gracz['username']}' został zaktualizowany! (Zmieniono {$affected_rows} rekord)";
// Odświeżamy dane gracza
$stmt_refresh = $db->prepare("SELECT * FROM players WHERE id = ?");
$stmt_refresh->bind_param("i", $player_id);
$stmt_refresh->execute();
$wynik_refresh = $stmt_refresh->get_result();
$gracz = $wynik_refresh->fetch_assoc();
$stmt_refresh->close();
} else {
$success_message = "Nie wprowadzono żadnych zmian (dane są identyczne)";
}
} else {
$errors[] = "Wystąpił błąd podczas aktualizacji: {$stmt->error}";
}
$stmt->close();
}
}
$db->close();
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Edycja profilu - <?= htmlspecialchars($gracz['username']) ?></title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
}
h1 {
margin-bottom: 10px;
color: #333;
}
.subtitle {
color: #666;
margin-bottom: 30px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
color: #555;
font-weight: 500;
}
input, select {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
}
input:focus, select:focus {
outline: none;
border-color: #667eea;
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
button {
width: 100%;
padding: 12px;
background: #667eea;
color: white;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
transition: background 0.3s;
}
button:hover {
background: #764ba2;
}
.error {
background: #f8d7da;
color: #721c24;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #f5c6cb;
}
.error ul {
margin-left: 20px;
}
.success {
background: #d4edda;
color: #155724;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #c3e6cb;
}
.info-box {
background: #e7f3ff;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #2196F3;
}
.back-link {
display: inline-block;
margin-top: 20px;
color: #667eea;
text-decoration: none;
}
.back-link:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="container">
<h1>Edycja profilu gracza</h1>
<div class="subtitle">ID: <?= $gracz['id'] ?> | Nick: <strong><?= htmlspecialchars($gracz['username']) ?></strong></div>
<?php if ($success): ?>
<div class="success">
<?= htmlspecialchars($success_message) ?>
</div>
<?php endif; ?>
<?php if (!empty($errors)): ?>
<div class="error">
<strong>Błędy walidacji:</strong>
<ul>
<?php foreach ($errors as $error): ?>
<li><?= htmlspecialchars($error) ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<div class="info-box">
<strong>Informacje:</strong><br>
• Nick gracza nie może być edytowany (to unikalna nazwa)<br>
• Hasło można zmienić w osobnej sekcji zabezpieczeń<br>
• Data rejestracji: <?= date('d.m.Y H:i', strtotime($gracz['created_at'])) ?>
</div>
<form method="POST">
<div class="form-group">
<label>Email:</label>
<input type="email" name="email"
value="<?= htmlspecialchars($gracz['email']) ?>"
required>
</div>
<div class="form-row">
<div class="form-group">
<label>Poziom (1-100):</label>
<input type="number" name="level"
min="1" max="100"
value="<?= $gracz['level'] ?>"
required>
</div>
<div class="form-group">
<label>Coins:</label>
<input type="number" name="coins"
min="0"
value="<?= $gracz['coins'] ?>"
required>
</div>
</div>
<div class="form-group">
<label>Ranga:</label>
<select name="rank_name" required>
<option value="Bronze" <?= $gracz['rank_name'] == 'Bronze' ? 'selected' : '' ?>>Bronze</option>
<option value="Silver" <?= $gracz['rank_name'] == 'Silver' ? 'selected' : '' ?>>Silver</option>
<option value="Gold" <?= $gracz['rank_name'] == 'Gold' ? 'selected' : '' ?>>Gold</option>
<option value="Platinum" <?= $gracz['rank_name'] == 'Platinum' ? 'selected' : '' ?>>Platinum</option>
<option value="Diamond" <?= $gracz['rank_name'] == 'Diamond' ? 'selected' : '' ?>>Diamond</option>
<option value="Master" <?= $gracz['rank_name'] == 'Master' ? 'selected' : '' ?>>Master</option>
<option value="Grandmaster" <?= $gracz['rank_name'] == 'Grandmaster' ? 'selected' : '' ?>>Grandmaster</option>
</select>
</div>
<button type="submit">Zapisz zmiany</button>
</form>
<a href="profil.php?id=<?= $player_id ?>" class="back-link">← Powrót do profilu</a>
</div>
</body>
</html>
PDO:
<?php
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=gaming_hub;charset=utf8mb4',
'root',
'',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
$errors = [];
$success = false;
$gracz = null;
// Pobieramy ID gracza z URL
$player_id = (int)($_GET['id'] ?? 0);
if ($player_id <= 0) {
die('Nieprawidłowe ID gracza');
}
// Pobieramy dane gracza do wyświetlenia w formularzu
$stmt = $pdo->prepare("SELECT * FROM players WHERE id = :id");
$stmt->execute(['id' => $player_id]);
$gracz = $stmt->fetch();
if (!$gracz) {
die('Nie znaleziono gracza o ID: ' . $player_id);
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Pobieramy dane z formularza
$email = trim($_POST['email'] ?? '');
$level = (int)($_POST['level'] ?? 1);
$coins = (int)($_POST['coins'] ?? 0);
$rank_name = $_POST['rank_name'] ?? 'Bronze';
// Walidacja danych
if (empty($email)) {
$errors[] = "Email jest wymagany";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "Nieprawidłowy format email";
}
if ($level < 1 || $level > 100) {
$errors[] = "Poziom musi być między 1 a 100";
}
if ($coins < 0) {
$errors[] = "Coins nie może być ujemny";
}
$allowed_ranks = ['Bronze', 'Silver', 'Gold', 'Platinum', 'Diamond', 'Master', 'Grandmaster'];
if (!in_array($rank_name, $allowed_ranks)) {
$errors[] = "Nieprawidłowa ranga";
}
// Sprawdzamy czy email nie jest już używany przez innego gracza
if (empty($errors)) {
$stmt = $pdo->prepare("SELECT id FROM players WHERE email = :email AND id != :id");
$stmt->execute(['email' => $email, 'id' => $player_id]);
if ($stmt->fetch()) {
$errors[] = "Email '{$email}' jest już używany przez innego gracza";
}
}
// Jeśli brak błędów - aktualizujemy dane
if (empty($errors)) {
// BEZPIECZNE - UPDATE z prepared statement
$stmt = $pdo->prepare("UPDATE players SET email = :email, level = :level, coins = :coins, rank_name = :rank_name, updated_at = NOW() WHERE id = :id");
if ($stmt->execute([
'email' => $email,
'level' => $level,
'coins' => $coins,
'rank_name' => $rank_name,
'id' => $player_id
])) {
// Sprawdzamy ile wierszy zostało zaktualizowanych
$affected_rows = $stmt->rowCount();
if ($affected_rows > 0) {
$success = true;
$success_message = "Profil gracza '{$gracz['username']}' został zaktualizowany! (Zmieniono {$affected_rows} rekord)";
// Odświeżamy dane gracza
$stmt_refresh = $pdo->prepare("SELECT * FROM players WHERE id = :id");
$stmt_refresh->execute(['id' => $player_id]);
$gracz = $stmt_refresh->fetch();
} else {
$success_message = "Nie wprowadzono żadnych zmian (dane są identyczne)";
}
}
}
}
} catch (PDOException $e) {
error_log("DB Error: {$e->getMessage()}");
die('Błąd bazy danych');
}
$pdo = null;
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Edycja profilu - <?= htmlspecialchars($gracz['username']) ?></title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
}
h1 {
margin-bottom: 10px;
color: #333;
}
.subtitle {
color: #666;
margin-bottom: 30px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
color: #555;
font-weight: 500;
}
input, select {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
}
input:focus, select:focus {
outline: none;
border-color: #667eea;
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
button {
width: 100%;
padding: 12px;
background: #667eea;
color: white;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
transition: background 0.3s;
}
button:hover {
background: #764ba2;
}
.error {
background: #f8d7da;
color: #721c24;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #f5c6cb;
}
.error ul {
margin-left: 20px;
}
.success {
background: #d4edda;
color: #155724;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #c3e6cb;
}
.info-box {
background: #e7f3ff;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #2196F3;
}
.back-link {
display: inline-block;
margin-top: 20px;
color: #667eea;
text-decoration: none;
}
.back-link:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="container">
<h1>Edycja profilu gracza</h1>
<div class="subtitle">ID: <?= $gracz['id'] ?> | Nick: <strong><?= htmlspecialchars($gracz['username']) ?></strong></div>
<?php if ($success): ?>
<div class="success">
<?= htmlspecialchars($success_message) ?>
</div>
<?php endif; ?>
<?php if (!empty($errors)): ?>
<div class="error">
<strong>Błędy walidacji:</strong>
<ul>
<?php foreach ($errors as $error): ?>
<li><?= htmlspecialchars($error) ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<div class="info-box">
<strong>Informacje:</strong><br>
• Nick gracza nie może być edytowany (to unikalna nazwa)<br>
• Hasło można zmienić w osobnej sekcji zabezpieczeń<br>
• Data rejestracji: <?= date('d.m.Y H:i', strtotime($gracz['created_at'])) ?>
</div>
<form method="POST">
<div class="form-group">
<label>Email:</label>
<input type="email" name="email"
value="<?= htmlspecialchars($gracz['email']) ?>"
required>
</div>
<div class="form-row">
<div class="form-group">
<label>Poziom (1-100):</label>
<input type="number" name="level"
min="1" max="100"
value="<?= $gracz['level'] ?>"
required>
</div>
<div class="form-group">
<label>Coins:</label>
<input type="number" name="coins"
min="0"
value="<?= $gracz['coins'] ?>"
required>
</div>
</div>
<div class="form-group">
<label>Ranga:</label>
<select name="rank_name" required>
<option value="Bronze" <?= $gracz['rank_name'] == 'Bronze' ? 'selected' : '' ?>>Bronze</option>
<option value="Silver" <?= $gracz['rank_name'] == 'Silver' ? 'selected' : '' ?>>Silver</option>
<option value="Gold" <?= $gracz['rank_name'] == 'Gold' ? 'selected' : '' ?>>Gold</option>
<option value="Platinum" <?= $gracz['rank_name'] == 'Platinum' ? 'selected' : '' ?>>Platinum</option>
<option value="Diamond" <?= $gracz['rank_name'] == 'Diamond' ? 'selected' : '' ?>>Diamond</option>
<option value="Master" <?= $gracz['rank_name'] == 'Master' ? 'selected' : '' ?>>Master</option>
<option value="Grandmaster" <?= $gracz['rank_name'] == 'Grandmaster' ? 'selected' : '' ?>>Grandmaster</option>
</select>
</div>
<button type="submit">Zapisz zmiany</button>
</form>
<a href="profil.php?id=<?= $player_id ?>" class="back-link">← Powrót do profilu</a>
</div>
</body>
</html>
Sprawdzanie wyniku operacji UPDATE
Metody sprawdzania dla MySQLi:
// 1. Sprawdź ile wierszy zostało zaktualizowanych
$affected_rows = $stmt->affected_rows; // Obiektowo
// 2. Sprawdź czy zapytanie się wykonało
if ($stmt->execute()) {
if ($affected_rows > 0) {
echo "Zaktualizowano {$affected_rows} rekord(ów)";
} else {
echo "Nie wprowadzono zmian (dane są identyczne)";
}
} else {
echo "Błąd: {$stmt->error}";
}
// 3. Sprawdź czy rekord istnieje przed UPDATE
$stmt_check = $db->prepare("SELECT id FROM players WHERE id = ?");
$stmt_check->bind_param("i", $player_id);
$stmt_check->execute();
$stmt_check->store_result();
if ($stmt_check->num_rows == 0) {
echo "Rekord o tym ID nie istnieje";
}
Metody sprawdzania dla PDO:
// 1. Sprawdź ile wierszy zostało zaktualizowanych
$affected_rows = $stmt->rowCount();
// 2. Sprawdź czy zapytanie się wykonało
if ($stmt->execute()) {
if ($affected_rows > 0) {
echo "Zaktualizowano {$affected_rows} rekord(ów)";
} else {
echo "Nie wprowadzono zmian (dane są identyczne)";
}
}
// 3. Sprawdź czy rekord istnieje przed UPDATE
$stmt_check = $pdo->prepare("SELECT id FROM players WHERE id = :id");
$stmt_check->execute(['id' => $player_id]);
if (!$stmt_check->fetch()) {
echo "Rekord o tym ID nie istnieje";
}
Przykład 4: Aktualizacja wielu graczy naraz (batch UPDATE)
MySQLi obiektowo:
<?php
mysqli_report(MYSQLI_REPORT_OFF);
$db = @new mysqli('localhost', 'root', '', 'gaming_hub');
if ($db->connect_error) {
die('Błąd połączenia');
}
$db->set_charset('utf8mb4');
// Przykład: Dodaj 100 coins wszystkim graczom Bronze
$rank = 'Bronze';
$bonus_coins = 100;
$stmt = $db->prepare("UPDATE players SET coins = coins + ? WHERE rank_name = ?");
$stmt->bind_param("is", $bonus_coins, $rank);
if ($stmt->execute()) {
$affected_rows = $stmt->affected_rows;
if ($affected_rows > 0) {
echo "Sukces! Dodano {$bonus_coins} coins dla {$affected_rows} graczy rangi {$rank}";
} else {
echo "Nie znaleziono graczy rangi {$rank} lub już mieli te coins";
}
} else {
echo "Błąd: {$stmt->error}";
}
$stmt->close();
$db->close();
?>
PDO:
<?php
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=gaming_hub;charset=utf8mb4',
'root',
'',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
// Przykład: Dodaj 100 coins wszystkim graczom Bronze
$rank = 'Bronze';
$bonus_coins = 100;
$stmt = $pdo->prepare("UPDATE players SET coins = coins + :bonus WHERE rank_name = :rank");
if ($stmt->execute(['bonus' => $bonus_coins, 'rank' => $rank])) {
$affected_rows = $stmt->rowCount();
if ($affected_rows > 0) {
echo "Sukces! Dodano {$bonus_coins} coins dla {$affected_rows} graczy rangi {$rank}";
} else {
echo "Nie znaleziono graczy rangi {$rank} lub już mieli te coins";
}
}
} catch (PDOException $e) {
error_log("DB Error: {$e->getMessage()}");
die('Błąd bazy danych');
}
$pdo = null;
?>
DELETE – Usuwanie rekordów
Przykład 5: Usuwanie gracza z potwierdzeniem (GET + POST)
MySQLi obiektowo:
<?php
mysqli_report(MYSQLI_REPORT_OFF);
$db = @new mysqli('localhost', 'root', '', 'gaming_hub');
if ($db->connect_error) {
die('Błąd połączenia');
}
$db->set_charset('utf8mb4');
$gracz = null;
$deleted = false;
// Pobieramy ID gracza z URL
$player_id = (int)($_GET['id'] ?? 0);
if ($player_id <= 0) {
die('Nieprawidłowe ID gracza');
}
// Pobieramy dane gracza do wyświetlenia
$stmt = $db->prepare("SELECT * FROM players WHERE id = ?");
$stmt->bind_param("i", $player_id);
$stmt->execute();
$wynik = $stmt->get_result();
$gracz = $wynik->fetch_assoc();
$stmt->close();
if (!$gracz) {
die('Nie znaleziono gracza o ID: ' . $player_id);
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['confirm_delete'])) {
// Dodatkowe zabezpieczenie - sprawdzamy token CSRF (opcjonalnie)
// if ($_POST['token'] !== $_SESSION['token']) die('Invalid token');
$stmt = $db->prepare("DELETE FROM players WHERE id = ?");
$stmt->bind_param("i", $player_id);
if ($stmt->execute()) {
// Sprawdzamy ile wierszy zostało usuniętych
$affected_rows = $stmt->affected_rows;
if ($affected_rows > 0) {
$deleted = true;
$username = htmlspecialchars($gracz['username']);
$success_message = "Gracz '{$username}' (ID: {$player_id}) został permanentnie usunięty z bazy danych.";
} else {
$error_message = "Rekord nie został usunięty (możliwe że już nie istnieje)";
}
} else {
$error_message = "Błąd podczas usuwania: {$stmt->error}";
}
$stmt->close();
}
$db->close();
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Usuń gracza - <?= htmlspecialchars($gracz['username'] ?? 'Usunięty') ?></title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.container {
background: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 10px 25px rgba(0,0,0,0.3);
max-width: 600px;
width: 100%;
}
h1 {
color: #d32f2f;
margin-bottom: 20px;
text-align: center;
}
.warning {
background: #fff3cd;
border-left: 4px solid #ffc107;
padding: 20px;
margin-bottom: 20px;
border-radius: 5px;
}
.player-info {
background: #f8f9fa;
padding: 20px;
border-radius: 5px;
margin-bottom: 20px;
}
.player-info h3 {
margin-bottom: 15px;
color: #333;
}
.player-info p {
margin: 8px 0;
color: #666;
}
.buttons {
display: flex;
gap: 10px;
margin-top: 30px;
}
button, .button {
flex: 1;
padding: 15px;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
text-align: center;
text-decoration: none;
display: inline-block;
}
.btn-delete {
background: #d32f2f;
color: white;
}
.btn-delete:hover {
background: #b71c1c;
}
.btn-cancel {
background: #6c757d;
color: white;
}
.btn-cancel:hover {
background: #5a6268;
}
.success {
background: #d4edda;
color: #155724;
padding: 20px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #c3e6cb;
text-align: center;
}
.error {
background: #f8d7da;
color: #721c24;
padding: 20px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #f5c6cb;
}
.checkbox-confirm {
margin: 20px 0;
display: flex;
align-items: center;
gap: 10px;
}
.checkbox-confirm input {
width: 20px;
height: 20px;
cursor: pointer;
}
.checkbox-confirm label {
cursor: pointer;
user-select: none;
}
</style>
</head>
<body>
<div class="container">
<?php if ($deleted): ?>
<div class="success">
<h2>Gracz został usunięty</h2>
<p><?= $success_message ?></p>
<br>
<a href="lista_graczy.php" class="button btn-cancel">← Powrót do listy graczy</a>
</div>
<?php else: ?>
<h1>Usuń gracza</h1>
<?php if (isset($error_message)): ?>
<div class="error">
<?= htmlspecialchars($error_message) ?>
</div>
<?php endif; ?>
<div class="warning">
<strong>OSTRZEŻENIE:</strong><br>
Ta operacja jest <strong>nieodwracalna</strong>! Gracz i wszystkie jego dane zostaną <strong>permanentnie usunięte</strong> z bazy danych.
</div>
<div class="player-info">
<h3>Dane gracza do usunięcia:</h3>
<p><strong>ID:</strong> <?= $gracz['id'] ?></p>
<p><strong>Username:</strong> <?= htmlspecialchars($gracz['username']) ?></p>
<p><strong>Email:</strong> <?= htmlspecialchars($gracz['email']) ?></p>
<p><strong>Level:</strong> <?= $gracz['level'] ?></p>
<p><strong>Rank:</strong> <?= $gracz['rank_name'] ?></p>
<p><strong>Coins:</strong> <?= number_format($gracz['coins']) ?></p>
<p><strong>Rozegrane gry:</strong> <?= $gracz['games_played'] ?></p>
<p><strong>Data rejestracji:</strong> <?= date('d.m.Y H:i', strtotime($gracz['created_at'])) ?></p>
</div>
<form method="POST">
<div class="checkbox-confirm">
<input type="checkbox" id="confirm" name="confirm_check" required>
<label for="confirm">Potwierdzam, że chcę <strong>permanentnie usunąć</strong> tego gracza</label>
</div>
<div class="buttons">
<a href="profil.php?id=<?= $player_id ?>" class="button btn-cancel">Anuluj</a>
<button type="submit" name="confirm_delete" class="btn-delete" onclick="return confirm('Czy NA PEWNO chcesz usunąć tego gracza? Ta operacja jest NIEODWRACALNA!')">
Usuń gracza
</button>
</div>
</form>
<?php endif; ?>
</div>
</body>
</html>
PDO:
<?php
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=gaming_hub;charset=utf8mb4',
'root',
'',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
$gracz = null;
$deleted = false;
// Pobieramy ID gracza z URL
$player_id = (int)($_GET['id'] ?? 0);
if ($player_id <= 0) {
die('Nieprawidłowe ID gracza');
}
// Pobieramy dane gracza do wyświetlenia
$stmt = $pdo->prepare("SELECT * FROM players WHERE id = :id");
$stmt->execute(['id' => $player_id]);
$gracz = $stmt->fetch();
if (!$gracz) {
die('Nie znaleziono gracza o ID: ' . $player_id);
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['confirm_delete'])) {
// Dodatkowe zabezpieczenie - sprawdzamy token CSRF (opcjonalnie)
// if ($_POST['token'] !== $_SESSION['token']) die('Invalid token');
// BEZPIECZNE - DELETE z prepared statement
$stmt = $pdo->prepare("DELETE FROM players WHERE id = :id");
if ($stmt->execute(['id' => $player_id])) {
// Sprawdzamy ile wierszy zostało usuniętych
$affected_rows = $stmt->rowCount();
if ($affected_rows > 0) {
$deleted = true;
$username = htmlspecialchars($gracz['username']);
$success_message = "Gracz '{$username}' (ID: {$player_id}) został permanentnie usunięty z bazy danych.";
} else {
$error_message = "Rekord nie został usunięty (możliwe że już nie istnieje)";
}
}
}
} catch (PDOException $e) {
error_log("DB Error: {$e->getMessage()}");
$error_message = "Wystąpił błąd podczas usuwania gracza";
}
$pdo = null;
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Usuń gracza - <?= htmlspecialchars($gracz['username'] ?? 'Usunięty') ?></title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.container {
background: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 10px 25px rgba(0,0,0,0.3);
max-width: 600px;
width: 100%;
}
h1 {
color: #d32f2f;
margin-bottom: 20px;
text-align: center;
}
.warning {
background: #fff3cd;
border-left: 4px solid #ffc107;
padding: 20px;
margin-bottom: 20px;
border-radius: 5px;
}
.player-info {
background: #f8f9fa;
padding: 20px;
border-radius: 5px;
margin-bottom: 20px;
}
.player-info h3 {
margin-bottom: 15px;
color: #333;
}
.player-info p {
margin: 8px 0;
color: #666;
}
.buttons {
display: flex;
gap: 10px;
margin-top: 30px;
}
button, .button {
flex: 1;
padding: 15px;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
text-align: center;
text-decoration: none;
display: inline-block;
}
.btn-delete {
background: #d32f2f;
color: white;
}
.btn-delete:hover {
background: #b71c1c;
}
.btn-cancel {
background: #6c757d;
color: white;
}
.btn-cancel:hover {
background: #5a6268;
}
.success {
background: #d4edda;
color: #155724;
padding: 20px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #c3e6cb;
text-align: center;
}
.error {
background: #f8d7da;
color: #721c24;
padding: 20px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #f5c6cb;
}
.checkbox-confirm {
margin: 20px 0;
display: flex;
align-items: center;
gap: 10px;
}
.checkbox-confirm input {
width: 20px;
height: 20px;
cursor: pointer;
}
.checkbox-confirm label {
cursor: pointer;
user-select: none;
}
</style>
</head>
<body>
<div class="container">
<?php if ($deleted): ?>
<div class="success">
<h2>Gracz został usunięty</h2>
<p><?= $success_message ?></p>
<br>
<a href="lista_graczy.php" class="button btn-cancel">← Powrót do listy graczy</a>
</div>
<?php else: ?>
<h1>Usuń gracza</h1>
<?php if (isset($error_message)): ?>
<div class="error">
<?= htmlspecialchars($error_message) ?>
</div>
<?php endif; ?>
<div class="warning">
<strong>OSTRZEŻENIE:</strong><br>
Ta operacja jest <strong>nieodwracalna</strong>! Gracz i wszystkie jego dane zostaną <strong>permanentnie usunięte</strong> z bazy danych.
</div>
<div class="player-info">
<h3>Dane gracza do usunięcia:</h3>
<p><strong>ID:</strong> <?= $gracz['id'] ?></p>
<p><strong>Username:</strong> <?= htmlspecialchars($gracz['username']) ?></p>
<p><strong>Email:</strong> <?= htmlspecialchars($gracz['email']) ?></p>
<p><strong>Level:</strong> <?= $gracz['level'] ?></p>
<p><strong>Rank:</strong> <?= $gracz['rank_name'] ?></p>
<p><strong>Coins:</strong> <?= number_format($gracz['coins']) ?></p>
<p><strong>Rozegrane gry:</strong> <?= $gracz['games_played'] ?></p>
<p><strong>Data rejestracji:</strong> <?= date('d.m.Y H:i', strtotime($gracz['created_at'])) ?></p>
</div>
<form method="POST">
<div class="checkbox-confirm">
<input type="checkbox" id="confirm" name="confirm_check" required>
<label for="confirm">Potwierdzam, że chcę <strong>permanentnie usunąć</strong> tego gracza</label>
</div>
<div class="buttons">
<a href="profil.php?id=<?= $player_id ?>" class="button btn-cancel">Anuluj</a>
<button type="submit" name="confirm_delete" class="btn-delete" onclick="return confirm('Czy NA PEWNO chcesz usunąć tego gracza? Ta operacja jest NIEODWRACALNA!')">
Usuń gracza
</button>
</div>
</form>
<?php endif; ?>
</div>
</body>
</html>
Sprawdzanie wyniku operacji DELETE
Metody sprawdzania dla MySQLi:
// 1. Sprawdź ile wierszy zostało usuniętych
$affected_rows = $stmt->affected_rows;
// 2. Sprawdź czy zapytanie się wykonało
if ($stmt->execute()) {
if ($affected_rows > 0) {
echo "Usunięto {$affected_rows} rekord(ów)";
} else {
echo "Nie usunięto żadnego rekordu (możliwe że nie istniał)";
}
} else {
echo "Błąd: {$stmt->error}";
}
Metody sprawdzania dla PDO:
// 1. Sprawdź ile wierszy zostało usuniętych
$affected_rows = $stmt->rowCount();
// 2. Sprawdź czy zapytanie się wykonało
if ($stmt->execute()) {
if ($affected_rows > 0) {
echo "Usunięto {$affected_rows} rekord(ów)";
} else {
echo "Nie usunięto żadnego rekordu (możliwe że nie istniał)";
}
}
PHP – Zabezpieczenie przed duplikatami po odświeżeniu strony (F5)
Problem: Ponowne wysłanie formularza
Co się dzieje gdy użytkownik naciśnie F5?
1. Użytkownik wypełnia formularz rejestracji
2. Klika "Wyślij" (POST)
3. Dane zostają zapisane w bazie
4. Strona wyświetla "Sukces!"
5. Użytkownik naciska F5 (odświeżenie)
6. Przeglądarka pyta: "Czy ponownie wysłać formularz?"
7. Jeśli użytkownik kliknie "Tak" → próba dodania tego samego gracza ponownie!
Konsekwencje:
- Duplikaty w bazie danych
- Błędy (jeśli są ograniczenia UNIQUE)
- Złe doświadczenie użytkownika
- Problemy z logowaniem transakcji
Rozwiązanie: Post/Redirect/Get (PRG Pattern)
Po wykonaniu operacji należy dodać kod
// PRZEKIEROWANIE - zapobiega duplikatom
header("Location: nazwa_strony.php?<dalej możemy przekazać dane w GET>;
exit; // ZAWSZE exit po header!
Przykład 1: Podstawowe przekierowanie
<?php
mysqli_report(MYSQLI_REPORT_OFF);
$db = @new mysqli('localhost', 'root', '', 'gaming_hub');
$db->set_charset('utf8mb4');
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = trim($_POST['username'] ?? '');
$email = trim($_POST['email'] ?? '');
// Walidacja...
$stmt = $db->prepare("INSERT INTO players (username, email, created_at) VALUES (?, ?, NOW())");
$stmt->bind_param("ss", $username, $email);
if ($stmt->execute()) {
$new_player_id = $stmt->insert_id;
$stmt->close();
$db->close();
// PRZEKIEROWANIE - zapobiega duplikatom
header("Location: profil.php?id={$new_player_id}");
exit; // ZAWSZE exit po header!
}
$stmt->close();
}
$db->close();
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Rejestracja</title>
</head>
<body>
<form method="POST">
<input type="text" name="username" required>
<input type="email" name="email" required>
<button type="submit">Zarejestruj</button>
</form>
</body>
</html>
Przykład 2: Przekazywanie informacji przez URL (GET)
<?php
mysqli_report(MYSQLI_REPORT_OFF);
$db = @new mysqli('localhost', 'root', '', 'gaming_hub');
$db->set_charset('utf8mb4');
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = trim($_POST['username'] ?? '');
$email = trim($_POST['email'] ?? '');
$level = (int)($_POST['level'] ?? 1);
// Walidacja...
$stmt = $db->prepare("INSERT INTO players (username, email, level, created_at) VALUES (?, ?, ?, NOW())");
$stmt->bind_param("ssi", $username, $email, $level);
if ($stmt->execute()) {
$new_player_id = $stmt->insert_id;
$affected_rows = $stmt->affected_rows;
$stmt->close();
$db->close();
// Przekazanie wielu informacji przez URL
header("Location: sukces.php?id={$new_player_id}&username=" . urlencode($username) . "&affected={$affected_rows}&action=register");
exit;
}
$stmt->close();
}
$db->close();
?>
Plik: sukces.php
<?php
// Odbieramy dane z URL
$new_player_id = (int)($_GET['id'] ?? 0);
$username = htmlspecialchars($_GET['username'] ?? 'Nieznany');
$affected_rows = (int)($_GET['affected'] ?? 0);
$action = htmlspecialchars($_GET['action'] ?? '');
if ($new_player_id <= 0) {
die('Nieprawidłowe ID');
}
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Rejestracja zakończona</title>
<style>
.success-box {
background: #d4edda;
color: #155724;
padding: 20px;
border-radius: 5px;
border-left: 4px solid #c3e6cb;
margin: 20px;
}
.info {
background: #d1ecf1;
color: #0c5460;
padding: 15px;
border-radius: 5px;
margin: 20px;
}
</style>
</head>
<body>
<div class="success-box">
<h2>Rejestracja zakończona sukcesem!</h2>
<p>Witaj, <strong><?= $username ?></strong>!</p>
</div>
<div class="info">
<strong>Szczegóły operacji:</strong><br>
ID nowego gracza: <strong><?= $new_player_id ?></strong><br>
Liczba dodanych rekordów: <strong><?= $affected_rows ?></strong><br>
Typ operacji: <strong><?= $action ?></strong><br>
<br>
<a href="profil.php?id=<?= $new_player_id ?>">Zobacz profil</a> |
<a href="lista_graczy.php">Lista graczy</a>
</div>
</body>
</html>
Zalety:
- Proste
- Nie wymaga sesji
- Działa zawsze
Wady:
- Dane widoczne w URL
- Ograniczona ilość danych (max ~2000 znaków)
- Nie nadaje się dla wrażliwych informacji
Przykład 3: Przekazywanie informacji przez SESJĘ
Kiedy używać:
- Komunikaty sukcesu/błędu
- Więcej danych
- Dane wrażliwe
- Profesjonalne projekty
<?php
session_start(); // ZAWSZE na początku pliku!
mysqli_report(MYSQLI_REPORT_OFF);
$db = @new mysqli('localhost', 'root', '', 'gaming_hub');
$db->set_charset('utf8mb4');
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = trim($_POST['username'] ?? '');
$email = trim($_POST['email'] ?? '');
$password = $_POST['password'] ?? '';
// Walidacja danych
if (empty($username)) {
$errors[] = "Nick jest wymagany";
} elseif (strlen($username) < 3) {
$errors[] = "Nick musi mieć minimum 3 znaki";
}
if (empty($email)) {
$errors[] = "Email jest wymagany";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "Nieprawidłowy format email";
}
if (empty($password)) {
$errors[] = "Hasło jest wymagane";
} elseif (strlen($password) < 8) {
$errors[] = "Hasło musi mieć minimum 8 znaków";
}
// Sprawdzamy czy username już istnieje
if (empty($errors)) {
$stmt = $db->prepare("SELECT id FROM players WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
$errors[] = "Nick '{$username}' jest już zajęty";
}
$stmt->close();
}
// Jeśli brak błędów - dodajemy gracza
if (empty($errors)) {
$password_hash = password_hash($password, PASSWORD_DEFAULT);
$stmt = $db->prepare("INSERT INTO players (username, email, password, created_at) VALUES (?, ?, ?, NOW())");
$stmt->bind_param("sss", $username, $email, $password_hash);
if ($stmt->execute()) {
// Pobieramy informacje o operacji
$new_player_id = $stmt->insert_id;
$affected_rows = $stmt->affected_rows;
$stmt->close();
$db->close();
// Zapisujemy dane w sesji
$_SESSION['registration_success'] = [
'player_id' => $new_player_id,
'username' => $username,
'email' => $email,
'affected_rows' => $affected_rows,
'timestamp' => date('Y-m-d H:i:s')
];
// Przekierowanie (URL czysty, bez danych)
header("Location: rejestracja_sukces.php");
exit;
} else {
$errors[] = "Wystąpił błąd podczas rejestracji: {$stmt->error}";
}
$stmt->close();
}
}
$db->close();
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Rejestracja gracza</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.container {
background: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
max-width: 500px;
width: 100%;
}
h1 {
margin-bottom: 30px;
color: #333;
text-align: center;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
color: #555;
font-weight: 500;
}
input {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
}
input:focus {
outline: none;
border-color: #667eea;
}
button {
width: 100%;
padding: 12px;
background: #667eea;
color: white;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
}
button:hover {
background: #764ba2;
}
.error {
background: #f8d7da;
color: #721c24;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #f5c6cb;
}
.error ul {
margin-left: 20px;
}
</style>
</head>
<body>
<div class="container">
<h1>Rejestracja Gracza</h1>
<?php if (!empty($errors)): ?>
<div class="error">
<strong>Błędy walidacji:</strong>
<ul>
<?php foreach ($errors as $error): ?>
<li><?= htmlspecialchars($error) ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label>Nick gracza:</label>
<input type="text" name="username"
value="<?= htmlspecialchars($_POST['username'] ?? '') ?>"
placeholder="np. ProGamer123"
required>
</div>
<div class="form-group">
<label>Email:</label>
<input type="email" name="email"
value="<?= htmlspecialchars($_POST['email'] ?? '') ?>"
placeholder="twoj@email.com"
required>
</div>
<div class="form-group">
<label>Hasło:</label>
<input type="password" name="password"
placeholder="Min. 8 znaków"
required>
</div>
<button type="submit">Zarejestruj się</button>
</form>
</div>
</body>
</html>
Plik: rejestracja_sukces.php
<?php
session_start(); // ZAWSZE na początku!
// Sprawdź czy istnieją dane o rejestracji
if (!isset($_SESSION['registration_success'])) {
// Jeśli ktoś próbuje wejść bezpośrednio na tę stronę
header("Location: rejestracja.php");
exit;
}
// Pobierz dane z sesji
$data = $_SESSION['registration_success'];
$player_id = (int)$data['player_id'];
$username = htmlspecialchars($data['username']);
$email = htmlspecialchars($data['email']);
$affected_rows = (int)$data['affected_rows'];
$timestamp = htmlspecialchars($data['timestamp']);
// Usuń dane z sesji (wyświetl tylko raz)
unset($_SESSION['registration_success']);
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Rejestracja zakończona</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.success-container {
background: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
max-width: 600px;
width: 100%;
}
.success-icon {
text-align: center;
font-size: 80px;
color: #28a745;
margin-bottom: 20px;
}
h1 {
text-align: center;
color: #155724;
margin-bottom: 20px;
}
.success-message {
background: #d4edda;
color: #155724;
padding: 20px;
border-radius: 5px;
border-left: 4px solid #c3e6cb;
margin-bottom: 30px;
}
.info-box {
background: #e7f3ff;
padding: 20px;
border-radius: 5px;
border-left: 4px solid #2196F3;
margin-bottom: 20px;
}
.info-box p {
margin: 8px 0;
color: #333;
}
.info-box strong {
color: #0c5460;
}
.buttons {
display: flex;
gap: 10px;
justify-content: center;
}
a {
padding: 12px 30px;
background: #667eea;
color: white;
text-decoration: none;
border-radius: 5px;
font-weight: bold;
text-align: center;
}
a:hover {
background: #764ba2;
}
</style>
</head>
<body>
<div class="success-container">
<div class="success-icon">✓</div>
<h1>Rejestracja zakończona sukcesem!</h1>
<div class="success-message">
<p>Witaj, <strong><?= $username ?></strong>!</p>
<p>Twoje konto zostało pomyślnie utworzone.</p>
</div>
<div class="info-box">
<p><strong>Szczegóły operacji:</strong></p>
<p>ID gracza: <strong><?= $player_id ?></strong></p>
<p>Username: <strong><?= $username ?></strong></p>
<p>Email: <strong><?= $email ?></strong></p>
<p>Liczba dodanych rekordów: <strong><?= $affected_rows ?></strong></p>
<p>Data rejestracji: <strong><?= $timestamp ?></strong></p>
</div>
<div class="buttons">
<a href="profil.php?id=<?= $player_id ?>">Zobacz profil</a>
<a href="logowanie.php">Zaloguj się</a>
<a href="lista_graczy.php">Lista graczy</a>
</div>
</div>
</body>
</html>
Zalety:
- Bezpieczne (dane niewidoczne w URL)
- Można przekazać wiele danych
- Komunikat wyświetla się tylko raz
- Profesjonalne rozwiązanie
Wady:
- Wymaga sesji
- Trochę więcej kodu
Przykład 4: UPDATE z informacją o affected_rows
<?php
session_start();
mysqli_report(MYSQLI_REPORT_OFF);
$db = @new mysqli('localhost', 'root', '', 'gaming_hub');
$db->set_charset('utf8mb4');
$player_id = (int)($_GET['id'] ?? 0);
if ($player_id <= 0) {
die('Nieprawidłowe ID gracza');
}
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = trim($_POST['email'] ?? '');
$level = (int)($_POST['level'] ?? 1);
$coins = (int)($_POST['coins'] ?? 0);
// Walidacja...
if (empty($email)) {
$errors[] = "Email jest wymagany";
}
if ($level < 1 || $level > 100) {
$errors[] = "Poziom musi być między 1 a 100";
}
if (empty($errors)) {
$stmt = $db->prepare("UPDATE players SET email = ?, level = ?, coins = ? WHERE id = ?");
$stmt->bind_param("siii", $email, $level, $coins, $player_id);
if ($stmt->execute()) {
$affected_rows = $stmt->affected_rows;
$stmt->close();
$db->close();
// Zapisz informacje w sesji
$_SESSION['update_result'] = [
'player_id' => $player_id,
'affected_rows' => $affected_rows,
'action' => 'update',
'message' => $affected_rows > 0
? "Profil został zaktualizowany ({$affected_rows} zmian)"
: "Nie wprowadzono żadnych zmian (dane są identyczne)"
];
// Przekierowanie
header("Location: profil.php?id={$player_id}");
exit;
}
$stmt->close();
}
}
$db->close();
?>
Plik: profil.php (wyświetlanie komunikatu)
<?php
session_start();
$player_id = (int)($_GET['id'] ?? 0);
// Sprawdź czy są dane o aktualizacji
$update_message = '';
$update_data = null;
if (isset($_SESSION['update_result'])) {
$update_data = $_SESSION['update_result'];
$update_message = $update_data['message'];
// Usuń z sesji po pobraniu
unset($_SESSION['update_result']);
}
// Połączenie i pobranie danych gracza...
mysqli_report(MYSQLI_REPORT_OFF);
$db = @new mysqli('localhost', 'root', '', 'gaming_hub');
$db->set_charset('utf8mb4');
$stmt = $db->prepare("SELECT * FROM players WHERE id = ?");
$stmt->bind_param("i", $player_id);
$stmt->execute();
$wynik = $stmt->get_result();
$gracz = $wynik->fetch_assoc();
$stmt->close();
$db->close();
if (!$gracz) {
die('Nie znaleziono gracza');
}
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Profil - <?= htmlspecialchars($gracz['username']) ?></title>
<style>
.success {
background: #d4edda;
color: #155724;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #c3e6cb;
}
.info {
background: #d1ecf1;
color: #0c5460;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #bee5eb;
}
</style>
</head>
<body>
<?php if (!empty($update_message)): ?>
<div class="<?= $update_data['affected_rows'] > 0 ? 'success' : 'info' ?>">
<?= htmlspecialchars($update_message) ?>
<?php if ($update_data['affected_rows'] > 0): ?>
<br><small>Liczba zaktualizowanych rekordów: <?= $update_data['affected_rows'] ?></small>
<?php endif; ?>
</div>
<?php endif; ?>
<h1>Profil gracza: <?= htmlspecialchars($gracz['username']) ?></h1>
<p>Email: <?= htmlspecialchars($gracz['email']) ?></p>
<p>Level: <?= $gracz['level'] ?></p>
<p>Coins: <?= number_format($gracz['coins']) ?></p>
<a href="edycja.php?id=<?= $player_id ?>">Edytuj profil</a>
</body>
</html>
Przykład 5: DELETE z potwierdzeniem i informacją o affected_rows
<?php
session_start();
mysqli_report(MYSQLI_REPORT_OFF);
$db = @new mysqli('localhost', 'root', '', 'gaming_hub');
$db->set_charset('utf8mb4');
$player_id = (int)($_GET['id'] ?? 0);
if ($player_id <= 0) {
die('Nieprawidłowe ID gracza');
}
// Pobierz dane gracza przed usunięciem
$stmt = $db->prepare("SELECT * FROM players WHERE id = ?");
$stmt->bind_param("i", $player_id);
$stmt->execute();
$wynik = $stmt->get_result();
$gracz = $wynik->fetch_assoc();
$stmt->close();
if (!$gracz) {
die('Nie znaleziono gracza');
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['confirm_delete'])) {
$stmt = $db->prepare("DELETE FROM players WHERE id = ?");
$stmt->bind_param("i", $player_id);
if ($stmt->execute()) {
$affected_rows = $stmt->affected_rows;
$stmt->close();
$db->close();
// Zapisz informacje w sesji
$_SESSION['delete_result'] = [
'username' => $gracz['username'],
'player_id' => $player_id,
'affected_rows' => $affected_rows,
'action' => 'delete',
'message' => $affected_rows > 0
? "Gracz '{$gracz['username']}' (ID: {$player_id}) został usunięty"
: "Nie usunięto gracza (możliwe że już nie istnieje)"
];
// Przekierowanie do listy graczy
header("Location: lista_graczy.php");
exit;
}
$stmt->close();
}
$db->close();
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Usuń gracza</title>
<style>
body {
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.container {
background: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 10px 25px rgba(0,0,0,0.3);
max-width: 600px;
width: 100%;
}
h1 {
color: #d32f2f;
margin-bottom: 20px;
}
.warning {
background: #fff3cd;
border-left: 4px solid #ffc107;
padding: 20px;
margin-bottom: 20px;
border-radius: 5px;
}
.player-info {
background: #f8f9fa;
padding: 20px;
border-radius: 5px;
margin-bottom: 20px;
}
.buttons {
display: flex;
gap: 10px;
}
button, a {
flex: 1;
padding: 15px;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
text-align: center;
text-decoration: none;
display: inline-block;
}
.btn-delete {
background: #d32f2f;
color: white;
}
.btn-delete:hover {
background: #b71c1c;
}
.btn-cancel {
background: #6c757d;
color: white;
}
.btn-cancel:hover {
background: #5a6268;
}
</style>
</head>
<body>
<div class="container">
<h1>Usuń gracza</h1>
<div class="warning">
<strong>OSTRZEŻENIE:</strong><br>
Ta operacja jest nieodwracalna! Gracz zostanie permanentnie usunięty z bazy danych.
</div>
<div class="player-info">
<h3>Dane gracza do usunięcia:</h3>
<p><strong>ID:</strong> <?= $gracz['id'] ?></p>
<p><strong>Username:</strong> <?= htmlspecialchars($gracz['username']) ?></p>
<p><strong>Email:</strong> <?= htmlspecialchars($gracz['email']) ?></p>
<p><strong>Level:</strong> <?= $gracz['level'] ?></p>
<p><strong>Coins:</strong> <?= number_format($gracz['coins']) ?></p>
</div>
<form method="POST">
<div class="buttons">
<a href="profil.php?id=<?= $player_id ?>" class="btn-cancel">Anuluj</a>
<button type="submit" name="confirm_delete" class="btn-delete"
onclick="return confirm('Czy NA PEWNO chcesz usunąć tego gracza?')">
Usuń gracza
</button>
</div>
</form>
</div>
</body>
</html>
Plik: lista_graczy.php (wyświetlanie komunikatu po usunięciu)
<?php
session_start();
// Sprawdź czy są dane o usunięciu
$delete_message = '';
$delete_data = null;
if (isset($_SESSION['delete_result'])) {
$delete_data = $_SESSION['delete_result'];
$delete_message = $delete_data['message'];
// Usuń z sesji po pobraniu
unset($_SESSION['delete_result']);
}
// Połączenie i pobranie listy graczy...
mysqli_report(MYSQLI_REPORT_OFF);
$db = @new mysqli('localhost', 'root', '', 'gaming_hub');
$db->set_charset('utf8mb4');
$stmt = $db->prepare("SELECT * FROM players ORDER BY id DESC");
$stmt->execute();
$wynik = $stmt->get_result();
$gracze = $wynik->fetch_all(MYSQLI_ASSOC);
$stmt->close();
$db->close();
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Lista graczy</title>
<style>
.success {
background: #d4edda;
color: #155724;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #c3e6cb;
}
.warning {
background: #fff3cd;
color: #856404;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 4px solid #ffeeba;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 12px;
border: 1px solid #ddd;
text-align: left;
}
th {
background: #667eea;
color: white;
}
</style>
</head>
<body>
<h1>Lista graczy</h1>
<?php if (!empty($delete_message)): ?>
<div class="<?= $delete_data['affected_rows'] > 0 ? 'success' : 'warning' ?>">
<?= htmlspecialchars($delete_message) ?>
<?php if ($delete_data['affected_rows'] > 0): ?>
<br><small>Liczba usuniętych rekordów: <?= $delete_data['affected_rows'] ?></small>
<?php endif; ?>
</div>
<?php endif; ?>
<table>
<tr>
<th>ID</th>
<th>Username</th>
<th>Email</th>
<th>Level</th>
<th>Akcje</th>
</tr>
<?php foreach ($gracze as $gracz): ?>
<tr>
<td><?= $gracz['id'] ?></td>
<td><?= htmlspecialchars($gracz['username']) ?></td>
<td><?= htmlspecialchars($gracz['email']) ?></td>
<td><?= $gracz['level'] ?></td>
<td>
<a href="profil.php?id=<?= $gracz['id'] ?>">Profil</a> |
<a href="edycja.php?id=<?= $gracz['id'] ?>">Edytuj</a> |
<a href="usun.php?id=<?= $gracz['id'] ?>">Usuń</a>
</td>
</tr>
<?php endforeach; ?>
</table>
</body>
</html>
Porównanie metod przekazywania danych:
| Metoda | Bezpieczeństwo | Złożoność | Dane w URL | Wielokrotne odświeżenie | Kiedy używać |
|---|---|---|---|---|---|
| GET (URL) | Niskie | Proste | Widoczne | Bezpieczne | Proste ID, niepoufne dane |
| SESSION | Wysokie | Średnie | Ukryte | Bezpieczne | Komunikaty, wrażliwe dane |
Najlepsze praktyki:
- ZAWSZE używaj przekierowania po INSERT/UPDATE/DELETE
- Używaj SESSION dla komunikatów i wrażliwych danych
- Używaj GET tylko dla ID i prostych parametrów
- Zapisuj
insert_idiaffected_rowsprzed przekierowaniem - Usuwaj dane z sesji po jednokrotnym wyświetleniu
- ZAWSZE dodawaj
exit;poheader() - Waliduj dane po stronie odbiorczej (nawet po przekierowaniu)