PHP MySQL voorbereide verklaringen
Voorbereide instructies zijn erg handig tegen SQL-injecties.
Voorbereide verklaringen en gebonden parameters
Een voorbereide instructie is een functie die wordt gebruikt om dezelfde (of vergelijkbare) SQL-instructies herhaaldelijk met hoge efficiëntie uit te voeren.
Voorbereide verklaringen werken in principe als volgt:
- Voorbereiden: Er wordt een SQL-instructiesjabloon gemaakt en naar de database verzonden. Bepaalde waarden worden niet gespecificeerd, parameters genoemd (aangeduid met "?"). Voorbeeld: INSERT INTO MyGuests VALUES(?, ?, ?)
- De database parseert, compileert en voert query-optimalisatie uit op de SQL-instructiesjabloon en slaat het resultaat op zonder het uit te voeren
- Uitvoeren: op een later tijdstip bindt de toepassing de waarden aan de parameters en voert de database de instructie uit. De toepassing kan de instructie zo vaak uitvoeren als hij wil met verschillende waarden
In vergelijking met het rechtstreeks uitvoeren van SQL-instructies hebben voorbereide instructies drie belangrijke voordelen:
- Voorbereide instructies verminderen de parseertijd omdat de voorbereiding van de query slechts één keer wordt gedaan (hoewel de instructie meerdere keren wordt uitgevoerd)
- Gebonden parameters minimaliseren de bandbreedte naar de server, omdat u elke keer alleen de parameters hoeft te verzenden, en niet de hele query
- Voorbereide instructies zijn erg handig tegen SQL-injecties, omdat parameterwaarden, die later met een ander protocol worden verzonden, niet correct hoeven te worden ontsnapt. Als de oorspronkelijke instructiesjabloon niet is afgeleid van externe invoer, kan SQL-injectie niet plaatsvinden.
Voorbereide verklaringen in MySQLi
In het volgende voorbeeld worden voorbereide instructies en gebonden parameters in MySQLi gebruikt:
Voorbeeld (MySQLi met voorbereide verklaringen)
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// prepare and bind
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);
// set parameters and execute
$firstname = "John";
$lastname = "Doe";
$email = "[email protected]";
$stmt->execute();
$firstname = "Mary";
$lastname = "Moe";
$email = "[email protected]";
$stmt->execute();
$firstname = "Julie";
$lastname = "Dooley";
$email = "[email protected]";
$stmt->execute();
echo "New records created successfully";
$stmt->close();
$conn->close();
?>
Coderegels om uit het bovenstaande voorbeeld uit te leggen:
"INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)"
In onze SQL voegen we een vraagteken (?) in waar we willen vervangen door een integer, string, double of blob-waarde.
Kijk dan eens naar de bind_param() functie:
$stmt->bind_param("sss", $firstname, $lastname, $email);
Deze functie bindt de parameters aan de SQL-query en vertelt de database wat de parameters zijn. Het argument "sss" geeft een overzicht van de soorten gegevens die de parameters zijn. Het s-teken vertelt mysql dat de parameter een string is.
Het argument kan een van de vier typen zijn:
- ik - geheel getal
- d - dubbel
- s - tekenreeks
- b - BLOB
We moeten een van deze hebben voor elke parameter.
Door mysql te vertellen welk type gegevens we kunnen verwachten, minimaliseren we het risico op SQL-injecties.
Opmerking: als we gegevens van externe bronnen (zoals gebruikersinvoer) willen invoegen, is het erg belangrijk dat de gegevens worden opgeschoond en gevalideerd.
Opgemaakte verklaringen in BOB
In het volgende voorbeeld worden voorbereide instructies en gebonden parameters in PDO gebruikt:
Voorbeeld (BOB met voorbereide verklaringen)
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// prepare sql and bind parameters
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email)
VALUES (:firstname, :lastname, :email)");
$stmt->bindParam(':firstname', $firstname);
$stmt->bindParam(':lastname', $lastname);
$stmt->bindParam(':email', $email);
// insert a row
$firstname = "John";
$lastname = "Doe";
$email = "[email protected]";
$stmt->execute();
// insert another row
$firstname = "Mary";
$lastname = "Moe";
$email = "[email protected]";
$stmt->execute();
// insert another row
$firstname = "Julie";
$lastname = "Dooley";
$email = "[email protected]";
$stmt->execute();
echo "New records created successfully";
} catch(PDOException $e)
{
echo "Error: " . $e->getMessage();
}
$conn = null;
?>