PHP Les 04: Veilig gegevens verwerken
Doelstelling les:
-
Bewustwording SQL injection
-
Kennismaken met prepared statements
-
Filterfunctie op basis van dropdown
Voorbereiding (studenten)
- Huiswerk vorige les natuurlijk
- Lees uit de reader paragraaf Prepared statements gebruiken van hoofdstuk Veilig gegevens verwerken
- Bekijk video's van CodeCourse op OnderwijsOnline:
- 23-CodeCourse-PDO-Fetch types.mp4
- 24-CodeCourse-PDO-Fetching all results.mp4
- 25-CodeCourse-PDO-Prepared Statements.mp4
Lesplan
- Huiswerk bespreken
- Componisten weergeven
- Prepared statements
Queries dynamisch maken
In deze les gaan we muziekstukken (uit de tabel Stuk) filteren op basis van genre (niet niveaucode want die is vaak NULL).
In de vorige les zijn we al bezig gegaan met data uit de database halen als de query vast staat. Nu gaan we bezig met een aanpassing op de query op basis van een gebruikers actie.
Stap 1: URL-filter toepassen
We gaan gebruik van van query-parameters (bijv. http://localhost:8080/muziekstukken.php?genrenaam=jazz)
Daarvoor gebruiken we de $_GET
superglobal.
-
Maak eerst de query in SQL Managament Studio.
-
Plak query in php-code
❗️ Let op, in de PHP moet je de single qoutes
'
escapen met\'
. Het is ook mogelijk om dubbele qoutes"
te gebruiken, maar dan zet je de deur weer open voor het per ongeluk uitvullen van variabelen (en dus voor sql injection). -
Vervang
jazz
metpop
en toon effect. -
Nu gaan we de query-parameters gebruiken zoals:
pop :
http://localhost:8080/muziekstukken.php?genrenaam=pop
jazz :
http://localhost:8080/muziekstukken.php?genrenaam=jazz
Dit kunnen we doen door direct met
$_GET
de query aan te passen, maar daar zitten nogal grote gevolgen aan. Want dan zetten we de deur open voor SQL-injection
Intermezzo: SQL-injection
De docent zal laten zien en vertellen wat de gevaren van SQL-injection zijn.
Stap 2: Query-parameters maar veilig met prepared statements
Nu gaan we prepared statements gebruiken. Zie ook het onderdeel in de H7. Veilig gegevens verwerken: Prepared Statements Gebruiken
Kort gezegd zijn prepared statements:
- voorbereidde queries, m.a.w. een query met placeholders
- Vaker te gebruiken, maar vooral een wapen tegen code injection
Recept voor prepared statements:
-
Maak query met placeholders:
SELECT .... FROM .... WHERE kolom = :kolom
(en:kolom
is de placeholder) -
Laat query door database voorbereiden:
$data = $db->prepare($sql)
-
Laat query uitvoeren met waardes voor de placeholders:
$data->execute(..waarden..)
-
Haal data op (fetch)
Stap 3: Dropdown menu met alle genres
Bovenaan de pagina gaan we nu een dropdown menu maken met behulp van:
- het <form> element met een
- <select> die verschillende <option>-elementen.
Denk goed na over welke "action"
en "method"
het formulier moet hebben.
Aan de hand van de <option> die gekozen is kun je nu de query draaien.
De query SELECT genrenaam FROM Genre
voer je nu uit met behulp van de data
die het formulier teruggeeft.
Bij de eerste aanroep krijg je een warning, die eerst even negeren. Speel wat met de pagina (selecteer af en toe een ander genre).
Stap 4: Warning weghalen met isset
Poets de warning weg door te controleren of genrenaam is meegegeven, anders een default waarde:
if(isset($_GET['genrenaam']))
{
$genrenaam = $_GET['genrenaam'];
}
else
{
$genrenaam = 'jazz'; // of een ander genre als default
}
Stap 5: Gegevens uit dropdown uit de database halen
De dropdown is nu hardcoded gevuld, maar die gegevens staan ook in de database. Als er nu een nieuw genre bij komt, dan moet je ook de html aanpassen. Dat gaan we dus met een query doen.
-
Voer eerst in SQL Management de query
INSERT INTO Genre(genrenaam) VALUES ('blues')
uit en laat zien dat die blues dus niet in de dropdown terecht komt. -
Maak een functie
getGenreSelectBox
die de select box genereert. -
Voeg nu nog een genre toe in SSMS:
INSERT INTO Genre(genrenaam) VALUES ('tranentrekker')
Nu kun je met het formulier dus stukken vinden op basis van de verschillende genres.
Stap 6: Voeg een nieuw muziekstuk toe
Voeg een nieuw stuk toe, bijvoorbeeld:
INSERT INTO stuk (stuknr, componistId, titel, genrenaam, jaartal)
VALUES (100, 10, 'Kneiterfalse', 'tranentrekker', 2021)`
Korte samenvatting
De docent zal het uiteindelijke formulier demonstreren en nog meer voorbeelden hiervan bespreken.
Welke voorbeelden kun je zelf bedenken?
Huiswerk
-
(verplicht) Nieuwe pagina maken met alle stukken, filter maken op basis van componistid (in de dropdown de naam zichtbaar, componistid is value)
-
(uitdaging, optioneel) in het formulier met de dropdown wordt de selectie niet bewaard, maar steeds op de eerste gezet. Een option als selected markeren doe je door
selected
op te nemen, bijv.<option value="klassiek" selected>klassiek</option>
. Geef de functiegetGenreSelectBox()
een argument$selection
wat het geselecteerde genre is. dus:function getGenreSelectBox($selection) { // Toevoegen: geef het geselecteerde genre `selected` $db = maakVerbinding(); $sql = 'select genrenaam from Genre'; $data = $db->query($sql); $selectbox = '<select id="genrenaam" name="genrenaam">'; foreach($data as $rij) { $genrenaam = $rij['genrenaam']; $selectbox .= "<option value=\"$genrenaam\">$genrenaam</option>"; } $selectbox .= '</select>'; return $selectbox; }
-
Voorbereiding volgende les