Przygotowane wyciągi PHP MySQL
Przygotowane instrukcje są bardzo przydatne w przypadku wstrzyknięć SQL.
Przygotowane oświadczenia i powiązane parametry
Przygotowana instrukcja to funkcja używana do wielokrotnego wykonywania tych samych (lub podobnych) instrukcji SQL z wysoką wydajnością.
Przygotowane zestawienia działają w zasadzie tak:
- Przygotuj: tworzony jest szablon instrukcji SQL i wysyłany do bazy danych. Niektóre wartości pozostają nieokreślone, nazywane parametrami (oznaczone „?”). Przykład: INSERT INTO MyGuests VALUES (?, ?, ?)
- Baza danych analizuje, kompiluje i przeprowadza optymalizację zapytań w szablonie instrukcji SQL i przechowuje wynik bez jego wykonywania
- Wykonaj: w późniejszym czasie aplikacja wiąże wartości z parametrami, a baza danych wykonuje instrukcję. Aplikacja może wykonać instrukcję tyle razy, ile chce z różnymi wartościami
W porównaniu z bezpośrednim wykonywaniem instrukcji SQL, przygotowane instrukcje mają trzy główne zalety:
- Przygotowane instrukcje skracają czas parsowania, ponieważ przygotowanie zapytania jest wykonywane tylko raz (chociaż instrukcja jest wykonywana wielokrotnie)
- Powiązane parametry minimalizują przepustowość do serwera, ponieważ za każdym razem musisz wysyłać tylko parametry, a nie całe zapytanie
- Przygotowane instrukcje są bardzo przydatne w przypadku wstrzyknięć SQL, ponieważ wartości parametrów, które są przesyłane później przy użyciu innego protokołu, nie muszą być poprawnie escapowane. Jeśli oryginalny szablon instrukcji nie pochodzi z danych wejściowych zewnętrznych, nie można wykonać wstrzyknięcia SQL.
Przygotowane oświadczenia w MySQLi
Poniższy przykład używa przygotowanych instrukcji i powiązanych parametrów w MySQLi:
Przykład (MySQLi z przygotowanymi instrukcjami)
<?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();
?>
Linie kodu do wyjaśnienia z powyższego przykładu:
"INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)"
W naszym SQL wstawiamy znak zapytania (?), w którym chcemy podstawić wartość całkowitą, łańcuchową, podwójną lub blob.
Następnie spójrz na funkcję bind_param():
$stmt->bind_param("sss", $firstname, $lastname, $email);
Ta funkcja wiąże parametry z zapytaniem SQL i informuje bazę danych, jakie są parametry. Argument „sss” wymienia typy danych, którymi są parametry. Znak s mówi mysql, że parametr jest łańcuchem.
Argument może być jednym z czterech typów:
- ja - liczba całkowita
- d - podwójne
- s - ciąg
- b - BLOB
Musimy mieć jeden z nich dla każdego parametru.
Mówiąc mysql jakiego typu danych ma się spodziewać, minimalizujemy ryzyko iniekcji SQL.
Uwaga: jeśli chcemy wstawić jakiekolwiek dane ze źródeł zewnętrznych (takich jak dane wprowadzone przez użytkownika), bardzo ważne jest, aby dane zostały oczyszczone i zweryfikowane.
Przygotowane oświadczenia w PDO
Poniższy przykład używa przygotowanych instrukcji i powiązanych parametrów w PDO:
Przykład (PDO z przygotowanymi oświadczeniami)
<?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;
?>