Bezpieczne zapytania (prepared statements)

Prepared statements w PHP chronią przed SQL Injection i innymi błędami związanymi z bezpośrednim wstawianiem danych do zapytań SQL. Dzięki nim parametry przekazywane są w bezpieczny sposób, co ułatwia obsługę zmiennych oraz zwiększa bezpieczeństwo aplikacji.


Na czym polegają prepared statements?

  • Oddzielenie zapytania od danych
    • Najpierw przygotowujesz szablon zapytania (z ? lub :param w PDO), a następnie przekazujesz dane osobno.
    • Silnik bazodanowy rozpoznaje, że parametry to zmienne, nie kawałek kodu SQL.
  • MySQLi – tryb obiektowy
    • Używasz $stmt = $conn->prepare("SELECT * FROM users WHERE login = ?");
    • Następnie $stmt->bind_param("s", $login); i $stmt->execute();
  • Korzyści
    • Zwiększone bezpieczeństwo (mniejsze ryzyko SQL Injection).
    • Możliwość wielokrotnego wykonywania zapytania z różnymi danymi.
Przykład
<?php
$host = "localhost";
$user = "root";
$pass = "";
$db   = "test_db";

// Połączenie
$conn = new mysqli($host, $user, $pass, $db);
if ($conn->connect_error) {
  die("Błąd połączenia: " . $conn->connect_error);
}

// Przygotowanie zapytania
$stmt = $conn->prepare("SELECT id, email FROM users WHERE login = ?");
if (!$stmt) {
  die("Błąd prepare: " . $conn->error);
}

// Przypisanie parametru (s oznacza string)
$login = "Ala";
$stmt->bind_param("s", $login);

// Wykonanie
$stmt->execute();

// Pobranie wyników
$result = $stmt->get_result();
if ($result->num_rows > 0) {
  while ($row = $result->fetch_assoc()) {
    echo "ID: {$row['id']}, Email: {$row['email']}<br>";
  }
} else {
  echo "Brak wyników.";
}

$stmt->close();
$conn->close();
?>
Zwrócona zawartość
[Wynik zależy od danych w tabeli users, np. „ID: 2, Email: [email protected]”]

Przykładowe zastosowania prepared statements

  • Logowanie
    • SELECT z warunkiem WHERE login = ?, by sprawdzić hasło i uniknąć wstrzyknięcia SQL.
  • Formularze kontaktowe
    • INSERT do tabeli wiadomości z parametrami ? lub :nazwa (w PDO).
  • Aktualizacja profilu
    • UPDATE ustawiany dynamicznie w zależności od danych użytkownika, np. WHERE id = ?.

Podsumowanie

  • Prepared statements rozdzielają kod SQL od wprowadzanych danych, zapobiegając SQL Injection.
  • W MySQLi używasz prepare(), bind_param() i execute(), a wynik pobierasz przez get_result().
  • To zalecany sposób wykonywania zapytań, zwłaszcza tych przyjmujących dane od użytkownika.
  • W praktyce znacznie poprawia bezpieczeństwo i stabilność aplikacji.