PHP MySQL Database
§ 8. MySQL Prepared
Gli statement precompilati sono molto utili contro le intrusioni SLQ.
§ 8.1. Statement precompilati e parametri collegati.
Gli statement precompilati sono una funzionalità usata per eseguire gli stessi statement SQL ripetutamente con alta efficienza.
Gli statement precompilati fondamentalmente funzionano così:
- Preparazione: uno modello di statement SQL viene creato e trasmesso al database. Alcuni valori sono lasciati non specificati. Sono chiamati parametri (etichettati "?"). Esempio: INSERT INTO MyGuest VALUES(?,?,?)
- Il database analizza, compila, ed esegue l'ottimizzazione della query nello statement precompilato, e immagazzina il risultato senza eseguirlo.
- Esecuzione: in un secondo momento, l'applicazione collega i valori ai parametri, e il database esegue lo statement. L'applicazione può eseguire lo statement quante volte vuole con differenti valori.
Rispetto all'esecuzione diretta, gli statement precompilati hanno tre vantaggi fondamentali:
- Gli statement precompilati riducono il tempo di analisi che viene fatta solo una volta mentre la query potrà essere eseguita tante volte.
- L'associazione dei parametri minimizza l'occupazione della linea di trasmissione in quanto vengono trasmessi solo i parametri e non tutta la query.
- Gli statement precompilati sono molto utili contro le intrusioni SQL, perchè i valori dei parametri, che sono trasmessi in un secondo tempo usando un diverso protocollo, non hanno bisogno di essere correttamente escaped. Se il modello originale non deriva da un imput esterno l'iniezione SQL non può verificarsi.
Su ques'ultimo punto non ci ho capito niente. Non sono riuscito a tradurre in maniera decente. Dovrò tornarci in seguito.
§ 8.2. Statement precompilati in MySQLi
<?php
$servername = "127.0.0.1";
$username = "mioUserName";
$password = "miaPassword";
$dbname = "myDB";
// Create connection
$conn = new mysqli($servername, $username,
$password, $dbname);
// Check connection
if ($conn->connect_error){
die("Connection failed: " . $conn->connect_error);
}
echo "<p class=phpoutput> Connessione mysqli object-oriented riuscita. </p>";
// prepare and bind
$stmt = $conn->prepare("INSERT INTO MyGuest_1 (firstname, lastname, email)
VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);
// set parameters and execute
$firstname = "John";
$lastname = "Doe";
$email = "john@example.com";
$stmt->execute();
$firstname = "Mary";
$lastname = "Moe";
$email = "mary@example.com";
$stmt->execute();
$firstname = "Julie";
$lastname = "Dooley";
$email = "julie@example.com";
$stmt->execute();
echo "<p class=phpoutput > Nuovi records creati con successo </p>";
$last_id = $conn->insert_id;
echo "<p class=phpoutput > Last inserted ID is: " . $last_id . "</p>";
$stmt->close();
$conn->close();
?>
Connessione mysqli object-oriented riuscita
Nuovi records creati con successo
Last inserted ID is: 8551
§ 8.2.1 Spiegazione deggli statement precompilati in MySQLi
"INSERT INTO MyGuest_1(firstname, lastname, email) VALUES(?, ?,?)"
Nel nostro SQL, inseriamo "?" dove vogliamo sostituire un valore integer, string, double o blob
vediamo ora il metodo bind_param():
$stmt->bind_param('sss',$firstname, $lastname, $email);
Questa funzione collega i parametri alla query SQL e dice al database di che tipo di parametro si tratta. L'argomento 'sss' elenca i tipi di parametro che seguono. In questo caso tre stringhe.
Gli argomenti possono essere di uno dei seguenti tipi:
- i: integer
- d: double
- s: string
- b: BLOB
Che tipo di dato sia BLOB ancora non lo so.
Dicendo a mysql il tipo di dato che ci aspettiamo riduciamo il rischio di iniezioni indesiderate.
Nota: Se vogliamo inserire dati da sorgenti esterne come ad esempio una form utente, è molto importante validare e sanare i dati.
§ 8.3. Statement precompilati in PDO
<?php
$servername = "127.0.0.1";
$username = "mioUserName";
$password = "miaPassword";
$dbname = "myDB";
try{
// Create connection
$conn = new PDO("mysql:host=$servername; dbname=$dbname",
$username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "<p class=phpoutput> Connessione pdo riuscita. </p>";
// prepare and bind
$stmt = $conn->prepare("INSERT INTO MyGuest_3 (firstname, lastname, email)
VALUES (:firstname, :lastname, :email)");
$stmt->bindParam(':firstname', $firstname);
$stmt->bindParam(':lastname', $lastname);
$stmt->bindParam(':email', $email);
// set parameters and execute
$firstname = "John";
$lastname = "Doe";
$email = "john@example.com";
$stmt->execute();
$firstname = "Mary";
$lastname = "Moe";
$email = "mary@example.com";
$stmt->execute();
$firstname = "Julie";
$lastname = "Dooley";
$email = "julie@example.com";
$stmt->execute();
echo "<p class=phpoutput > Nuovi records creati con successo </p>";
$last_id = $conn->lastInsertId();
echo "<p class=phpoutput > Last inserted ID is: " . $last_id . "</p>";
}
catch(PDOException $e) {
echo "<p class=phpoutput >". $sql. "</p>";
echo "<p class=phpoutput >". $e->getMessage(). "</p>";
}
if ($stmt != null){
$stmt = null;
}
if ($conn != null){
$conn = null;
}
?>
Connessione pdo riuscita
Nuovi records creati con successo
Last inserted ID is: 3