Query preparate
Il problema
Sezione intitolata “Il problema”Quando una query contiene dati inseriti dall’utente, non devi inserirli direttamente nella stringa SQL.
Questo è pericoloso:
<?php$sql = "SELECT * FROM utenti WHERE email = '$email'";Se $email contiene testo malevolo, la query può cambiare significato. Questo rischio si chiama SQL injection.
Prepared statement
Sezione intitolata “Prepared statement”Una query preparata separa la struttura della query dai suoi valori.
<?php$sql = "SELECT * FROM utenti WHERE email = :email";$stmt = $pdo->prepare($sql);$stmt->execute(["email" => $email]);
$utente = $stmt->fetch();:email è un placeholder, cioè un segnaposto. Il valore effettivo arriva dopo, separato dalla query.
SELECT sicura
Sezione intitolata “SELECT sicura”<?php$email = $_POST["email"] ?? "";
$stmt = $pdo->prepare("SELECT * FROM utenti WHERE email = :email");$stmt->execute(["email" => $email]);
$utente = $stmt->fetch();
if ($utente) { echo "Utente trovato";}fetch legge una riga. Se non ci sono risultati, restituisce false.
INSERT sicuro
Sezione intitolata “INSERT sicuro”<?php$stmt = $pdo->prepare( "INSERT INTO utenti (nome, email) VALUES (:nome, :email)");
$stmt->execute([ "nome" => $nome, "email" => $email,]);Anche qui i valori restano separati dalla query.
Regola pratica
Sezione intitolata “Regola pratica”Ogni volta che una query usa dati esterni, usa prepare ed execute con placeholder. È una delle abitudini più importanti per scrivere PHP sicuro con i database.
Placeholder con punto interrogativo
Sezione intitolata “Placeholder con punto interrogativo”Oltre ai placeholder con nome, puoi usare ?.
<?php$stmt = $pdo->prepare("SELECT * FROM utenti WHERE email = ?");$stmt->execute([$email]);Funziona bene per query piccole. I placeholder con nome sono spesso più leggibili quando i valori sono molti.
Leggere più righe
Sezione intitolata “Leggere più righe”Per una lista di risultati usa fetchAll.
<?php$stmt = $pdo->prepare("SELECT * FROM prodotti WHERE prezzo < :massimo");$stmt->execute(["massimo" => 20]);
$prodotti = $stmt->fetchAll();
foreach ($prodotti as $prodotto) { echo $prodotto["nome"] . "\n";}La query resta sicura perché il valore 20 viene passato separatamente.
Errore comune: preparare e poi incollare lo stesso
Sezione intitolata “Errore comune: preparare e poi incollare lo stesso”Questo non va bene:
<?php$stmt = $pdo->prepare("SELECT * FROM utenti WHERE email = '$email'");Anche se usi prepare, hai comunque inserito $email nella stringa. Il valore deve passare attraverso un placeholder.