De regels voor het toevoegen van een PHP-variabele in een MySQL-statement zijn duidelijk en eenvoudig:
- Elke variabele die een SQL data literal vertegenwoordigt , (of, om het simpel te zeggen - een SQL-string, of een getal) MOET worden toegevoegd via een voorbereide instructie. Geen uitzonderingen.
- Elk ander zoekgedeelte, zoals een SQL-sleutelwoord, een tabel- of veldnaam of een operator, moet worden gefilterd door een witte lijst .
Dus omdat uw voorbeeld alleen data-letters bevat, moeten alle variabelen worden toegevoegd via tijdelijke aanduidingen (ook wel parameters genoemd). Om dit te doen:
- Vervang in uw SQL-instructie alle variabelen door plaatsaanduidingen
- voorbereiden de resulterende zoekopdracht
- binden variabelen naar tijdelijke aanduidingen
- uitvoeren de vraag
En hier is hoe het te doen met alle populaire PHP-databasestuurprogramma's:
Dataliteralen toevoegen met mysql ext
Zo'n stuurprogramma bestaat niet .
Dataliteralen toevoegen met mysqli
$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description)
VALUES(?, ?, 'whatever')";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("ss", $type, $reporter);
$stmt->execute();
De code is een beetje ingewikkeld, maar de gedetailleerde uitleg van al deze operators is te vinden in mijn artikel, Hoe een INSERT-query met Mysqli , evenals een oplossing die het proces aanzienlijk vereenvoudigt.
Voor een SELECT-query hoeft u slechts een aanroep toe te voegen aan get_result()
methode om een vertrouwd mysqli_result
. te krijgen waaruit u de gegevens op de gebruikelijke manier kunt ophalen:
$reporter = "John O'Hara";
$stmt = $mysqli->prepare("SELECT * FROM users WHERE name=?");
$stmt->bind_param("s", $reporter);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc(); // or while (...)
Dataliteralen toevoegen met PDO
$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description)
VALUES(?, ?, 'whatever')";
$stmt = $pdo->prepare($query);
$stmt->execute([$type, $reporter]);
In PDO kunnen we de onderdelen binden en uitvoeren combineren, wat erg handig is. PDO ondersteunt ook benoemde tijdelijke aanduidingen, wat sommigen erg handig vinden.
Trefwoorden of ID's toevoegen
Soms moeten we een variabele toevoegen die een ander deel van een query vertegenwoordigt, zoals een trefwoord of een identifier (een database, tabel of een veldnaam). Het is een zeldzaam geval, maar het is beter om voorbereid te zijn.
In dit geval moet uw variabele expliciet worden vergeleken met een lijst met waarden geschreven in je script. Dit wordt uitgelegd in mijn andere artikel, Een veldnaam toevoegen in de ORDER BY-clausule op basis van de keuze van de gebruiker :
Helaas heeft PDO geen tijdelijke aanduiding voor identifiers (tabel- en veldnamen), daarom moet een ontwikkelaar ze handmatig uitfilteren. Zo'n filter wordt vaak een "witte lijst" genoemd (waarbij we alleen toegestane waarden vermelden) in tegenstelling tot een "zwarte lijst" waar we niet-toegestane waarden vermelden.
We moeten dus expliciet alle mogelijke varianten in de PHP-code vermelden en daaruit kiezen.
Hier is een voorbeeld:
$orderby = $_GET['orderby'] ?: "name"; // set the default value
$allowed = ["name","price","qty"]; // the white list of allowed field names
$key = array_search($orderby, $allowed, true); // see if we have such a name
if ($key === false) {
throw new InvalidArgumentException("Invalid field name");
}
Precies dezelfde benadering moet worden gebruikt voor de richting,
$direction = $_GET['direction'] ?: "ASC";
$allowed = ["ASC","DESC"];
$key = array_search($direction, $allowed, true);
if ($key === false) {
throw new InvalidArgumentException("Invalid ORDER BY direction");
}
Na zo'n code, beide $direction
en $orderby
variabelen kunnen veilig in de SQL-query worden geplaatst, omdat ze ofwel gelijk zijn aan een van de toegestane varianten, of er zal een fout optreden.
Het laatste om te vermelden over identifiers, ze moeten ook worden geformatteerd volgens de specifieke databasesyntaxis. Voor MySQL moet het backtick
zijn tekens rond de identifier. Dus de laatste vraagreeks voor onze voorbeeldvolgorde zou zijn
$query = "SELECT * FROM `table` ORDER BY `$orderby` $direction";