|
|
Inleiding |
|
In de vorige hoofdstukken heb je geleerd om een connectie met een database management service te leggen en gegevens op te vragen uit deze database. Er is ook een begin gemaakt met een eenvoudige website voor de administratie van een webwinkel. Gegevens opvragen is belangrijk, maar even belangrijk is het opslaan van gegevens in de database. We gaan nu de eenvoudige website uitbreiden met de invoer van een nieuw product. Een HTML formulier en de verwerking van een formulier zijn daarbij natuurlijk een noodzaak. Ben je die techniek vergeten kijk dan in de cursus Interactieve website: PhP . Hoofdstuk 3 in die cursus geeft het snelst het gewenste inzicht.
Aan het einde van dit hoofdstuk weet je :
|
|
|
|
Invoeren van gegevens |
|
Dit hoofdstuk ga je gegevens invoeren in een database. Het opslaan van gegevens
vanuit php vindt ook weer plaats via SQL code. In de regel hieronder vind je
de SQL instructie voor het invoeren van een specifiek product.
INSERT INTO product (id, naam, prijs, voorraad, omschrijving) VALUES ('', 'Motorolie','25.99','60','Motorolie van zeer hoge kwaliteit')Merk op dat voor het veld id een lege waarde ('') wordt verstuurd. De reden is dat in mysql automatische nummering voor dit veld is ingeschakeld en krijgt dit veld bij invoer automatisch een unieke waarde toegewezen. Het veld kan om deze reden ook volledig worden weggelaten. INSERT INTO product (naam, prijs, voorraad, omschrijving) VALUES ('Motorolie','25.99','60','Motorolie van zeer hoge kwaliteit') Om deze SQL opdracht in de code te kunnen gebruiken moet deze algemener worden gemaakt, want we moeten met een formulier de informatie voor een willekeurig product kunnen opsturen. De verwerking moet op een veilige manier gebeuren, want gebruikers zouden door middel van SQL injection een aanval op de database kunnen doen. Volg de link en lees hoe SQL Injection werkt. Hier wordt met de techniek "Prepared Statements" gepoogd SQL Injection te voorkomen. Dit gaat in PDO als volgt. We veranderen de query naar: $query ="INSERT INTO product (naam,prijs,voorraad,omschrijving) VALUES (:naam, :prijs, :voorraad, :omschrijving)"; In PDO zijn :naam, :prijs, :voorraad en :omschrijving een soort van variabelen die daarna aan overeenkomstige variabelen in php worden gekoppeld. In ons voorbeeld zijn dat $naam, $prijs, $voorraad en $omschrijving. Als die variabelen gevuld zijn dan wordt de volledige instructie in php: $query = "INSERT INTO product (naam,prijs,voorraad,omschrijving) VALUES (:naam, :prijs, :voorraad, :omschrijving)"; $opdracht = $db->prepare($query); $opdracht->bindParam(':naam', $naam); $opdracht->bindParam(':prijs', $prijs); $opdracht->bindParam(':voorraad', $voorraad); $opdracht->bindParam(':omschrijving', $omschrijving); $opdracht->execute(); In de voorbeeld code in product.php is deze instructie nog met wat extra controles omgeven. |
|
|
|
Praktijkvoorbeeld |
|
Opdrachten |
|
voorbeeld 3: index.php |
<?php //Laad database code require_once("database.php"); //Laad algemene code require_once("algemeen.php"); //Laad code voor de acties met betrekking tot producten die we op de database gaan doen require_once("product.php"); // declareren van variabelen $menu = getMenu(); // Haal het menu door de functie getMenu() uit algemeen.php op te roepen $actie=""; $uitvoer = ""; if( isset($_POST['actie']) && !empty($_POST['actie'])) { $actie=$_POST['actie']; } // afhandelen actie ofwel uitvoer maken switch($actie) { case "Invoeren": // Voer de functie artikelInvoeren() in product.php uit $uitvoer=artikelInvoeren($db); break; case "Voeg Product Toe": // Voer de functie toonArtikelInvoerTabel in acties.php uit met 4 lege waarde fout paren $uitvoer=toonArtikelInvoerTabel(legeInvoerEnFout(4),true); break; case "Toon VerbindingStatus": $uitvoer = toonVerbindingStatus(); break; case "Toon Artikelen": default: $uitvoer=toonArtikelenLijst(); } /* Met onderstaand echo commando kun je een stuk text tussen END en END; naar de client computer sturen */ echo <<<END <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Page title</title> <style type="text/css"> td { border-bottom: 1px groove black; } tr:nth-child(odd) { background-color: lightblue; } </style> </head> <body> <h1>Garagebedrijf</h1> <form action='{$_SERVER['PHP_SELF']}' method="post" > $menu </form> <hr> <form action='{$_SERVER['PHP_SELF']}' method="post" > $uitvoer </form> </body> </html> END; //einde van het PhP blok ?> |
voorbeeld 3: functies voor algemeen.php |
De functie getMenu/* getMenu geeft de code voor het menu in de website */ function getMenu() { $uitvoer=<<<END <table class='menu' summary=""> <tr> <td><input type="submit" name="actie" value="Toon Artikelen"> </td> <td><input type="submit" name="actie" value="Voeg Product Toe"> </td> <td><input type="submit" name="actie" value="Toon VerbindingStatus"> </td> </tr> </table> END; return $uitvoer; } De functie legeInvoerEnFoutDe volgende functie voegen we toe omdat die straks bij het invoeren van medewerkers en klanten ook nuttig is. Bij ieder veld dat je moet invullen hoort een waarde en je kan een fout bij het invullen maken. De waarden en de fouten moeten we kunnen volgen tussen de verschillende schermen. /** * legeInvoerEnFout maakt een dubbele array met lege strings * die staan voor waarde-fout paren * $aantal is aantal gewenste waarde-fout paren */ function legeInvoerEnFout($aantal) { $resultaat = array(); // voeg per iteratie een waarde-fout paar toe for($i=0;$i<$aantal;$i++) $resultaat[$i]=array("",""); return $resultaat; } |
voorbeeld 3: functies voor product.php |
De functie toonArtikelInvoerTabelDe functie toonArtikelInvoerTabel is een voorbeeld van een functie die meerdere argumenten nodig heeft om te kunnen werken./** * toonArtikelInvoerTabel toont de tabel waarmee een product kan worden ingevoerd * of het resultaat van de invoer actie kan laten zien * param $productEnFout: lijst van producteigenschappen bestaande uit * 4 invoer velden en eventuele fouten * [ [naam,foutnaam], [prijs,foutprijs], [voorraad,foutvoorraad], [omschrijving,omschrijving], * ] * param $alsFormulier true als formulier getoond moet worden, false als alleen de informatie getoond moet worden */ function toonArtikelInvoerTabel($productEnFout,$alsFormulier) { $invoer1=""; $invoer2=""; $invoer3=""; $invoer4=""; $invoerknop=""; // Voeg hier eigen commentaar toe. //print_r($productEnFout); // Voeg hier eigen commentaar toe. if($alsFormulier) { $invoer1="<input name='naam' value='{$productEnFout[0][0]}'/>"; // naam $invoer2="<input name='prijs' value='{$productEnFout[1][0]}'/>"; // prijs $invoer3="<input name='voorraad' value='{$productEnFout[2][0]}'/>"; // voorraad $invoer4="<textarea name='omschrijving'/>{$productEnFout[3][0]}</textarea>"; // omschrijving $invoerknop=<<<END <tr> <td colspan="3"> <input type="submit" name="actie" value="Invoeren"/> </td> </tr> END; } else { $invoer1=$productEnFout[0][0]; // naam $invoer2=$productEnFout[1][0]; // prijs $invoer3=$productEnFout[2][0]; // voorraad $invoer4=$productEnFout[3][0]; // omschrijving } // Voeg hier eigen commentaar toe. $uitvoer=<<<END <h3>Voer artikel in</h3> <table> <tr> <td>Geef naam artikel</td> <td>$invoer1</td> </td> <td>{$productEnFout[0][1]}</td> </tr> <tr> <td>Geef prijs</td> <td>$invoer2</td> <td>{$productEnFout[1][1]}</td> </tr> <tr> <td>Geef aantal in voorraad</td> <td>$invoer3</td> <td>{$productEnFout[2][1]}</td> </tr> <tr> <td>Geef omschrijving</td> <td>$invoer4</td> <td>{$productEnFout[3][1]}</td> </tr> $invoerknop </table> END; return $uitvoer; } De functie artikelInvoerenDe functie artikelInvoeren is de langste van het stel./* * artikelInvoeren leest de invoer uit de $_POST variabele, * test de invoer, geeft foutmeldingen bij mislukkingen en voegt als * er niets misgaat een record toe aan de database. * param &$db: verwijzing naar de database */ function artikelInvoeren(&$db) { $fout1=""; $fout2=""; $fout3=""; $fout4=""; $naam = ""; $prijs = ""; $voorraad = ""; $omschrijving = ""; $uitvoer =""; $melding=""; //verbinding maken met database if(!$db) maakVerbinding($db,$melding); if(!$db) // test verbinding { // mislukt $uitvoer=$melding; } else { // isset is een functie die kijkt of een element in een array bestaat // post variabelen ophalen // https://www.w3schools.com/php/php_mysql_prepared_statements.asp // prepared statements worden gebruikt om sql injection te voorkomen try{ $query = "INSERT INTO product (naam,prijs,voorraad,omschrijving) VALUES (:naam, :prijs, :voorraad, :omschrijving)"; $opdracht = $db->prepare($query); $opdracht->bindParam(':naam', $naam); $opdracht->bindParam(':prijs', $prijs); $opdracht->bindParam(':voorraad', $voorraad); $opdracht->bindParam(':omschrijving', $omschrijving); if(isset($_POST["prijs"])) { $prijs = $_POST["prijs"]; } if(isset($_POST["naam"])) { $naam = $_POST["naam"]; } if(isset($_POST["voorraad"])) { $voorraad = $_POST["voorraad"]; } if(isset($_POST["omschrijving"])) { $omschrijving= $_POST["omschrijving"]; } // test of er waarden en getallen zijn // Voeg hier eigen commentaar toe. if( !empty($naam) && ((!empty($prijs) && is_numeric($prijs))||$prijs=="0") && ((!empty($voorraad) && is_numeric($voorraad))||$voorraad=="0") && !empty($omschrijving) ) { // Maak van prijs een double $prijs=(double)$prijs; //Alle waarden voor de invoer zouden nu goed moeten zijn // en zijn we nu klaar om de opdracht door te geven aan database $opdracht->execute(); $uitvoer = toonArtikelInvoerTabel( array( array($naam,$fout1), array($prijs,$fout2), array($voorraad,$fout3), array($omschrijving,$fout4) ),false); $uitvoer .= "Artikel is ingevoerd"; } else // er is een fout in waarden { // Voeg hier eigen commentaar toe. if(empty($naam)){$fout1="Er moet een naam worden ingevuld";} if(empty($prijs)){$fout2="Er moet een getal worden ingevuld";} elseif(!is_numeric($prijs)){$fout2="$prijs is geen getal";} if(empty($voorraad)){$fout3="Er moet een getal worden ingevuld";} elseif(!is_numeric($voorraad)){$fout3="$voorraad is geen getal";} if(empty($omschrijving)){$fout4="Er moet een omschrijving worden ingevuld";} $uitvoer = toonArtikelInvoerTabel( array( array($naam,$fout1), array($prijs,$fout2), array($voorraad,$fout3), array($omschrijving,$fout4) ),true); } } catch(PDOException $e) { // Er is een fout opgetreden in SQL $uitvoer = toonArtikelInvoerTabel( array( array($naam,$fout1), array($prijs,$fout2), array($voorraad,$fout3), array($omschrijving,$fout4) ),true); $uitvoer .= "Fout uitvoeren query!<br/>"; $uitvoer .= $e->getMessage(); } //sluit database verbreekVerbinding($db); } return $uitvoer; } |
|