Programmeren in PHP/Gebruikersinvoer
Invoer van gebruikers is belangrijk in de wereld van webscripting. Veel software maakt er gebruik van, waaronder Wikipedia, de meeste fora en simpele gastenboeken. Dit wordt ook wel de frontend genoemd, omdat dit is wat de gebruiker te zien krijgt. We gaan nu zo'n frontend maken voor een gastenboek, het opslaan/bewaren komt in de volgende paragrafen aan bod. De invoer die binnenkomt kan op drie manieren binnen komen, namelijk.
POST
bewerkenDe waarde voor een POST zitten in de $_POST array, in een iets wat oudere versie zitten deze in de $HTTP_POST_VARS array. Er wordt vanuit gegaan dat je de laatste stabiele versie hebt (op het moment van schrijven is dit 5.4.11). De $_POST array wordt meestal gevuld door een HTML form waarbij het attribuut "method" de waarde "post" heeft.
PHP-code:
<html>
<head>
<title>
Gastenboek
</title>
</head>
<body>
<form method="post" action="verwerk.php">
<input type="text" name="Naam" value="" />
<textarea cols="20" rows="20"></textarea>
<input type="submit" value="Verstuur" />
</form>
</body>
</html>
Het formulier wijst naar het bestand verwerk.php. Wanneer er op verstuur wordt geklikt wordt dit bestand uitgevoerd. Wanneer je in verwerk.php wilt weten wat de gebruiker heeft ingevoerd kun je de variabele $_POST["Naam"] gebruiken. Zoals je kunt zien is dit een array. Hierin zet PHP de waardes die een formulier verstuurt. De array is associatief, wat wil zeggen dat de sleutel voor elke waarde een stuk tekst is in plaats van een getal.
GET
bewerkenBij een formulier kan ook de methode "get" worden gebruikt. Deze werkt exact hetzelfde als hierboven, met het verschil dat method="post" moet worden method="get" en de variabele in verwerk.php nu $_GET['Naam'] is.
Waarom twee manieren dan? Dat is heel simpel: Wanneer get wordt gebruikt staan de opgegeven waardes in de URL: http://www.mijnwebsite.nl/verwerk.php?Naam=henk Wanneer post wordt gebruikt wordt dit niet in de URL weergegeven. Het grote voordeel van 'get' is dat je ook een directe link kunt maken met een waarde hierin. Het voordeel van 'post' is dat je veel meer gegevens kwijt kunt (de URL mag maar rond de 2.000 tekens lang zijn) en dat niet iedereen eenvoudig de gegevens kan bekijken.
Invoer valideren
bewerkenHet is belangrijk om altijd invoer die je krijgt van de gebruiker te valideren. Hiervoor kun je een hele hoop functies gebruiken:
- is_numeric($var) geeft "TRUE" als $var een getal is, false als dat niet zo is
- is_string($var) geeft "TRUE" als $var een string is, false als dat niet zo is
- isset($var) geeft "TRUE" als $var bestaat
- empty($var) geeft "TRUE" als $var leeg is
Checken doe je dan zo:
PHP-code:
<?php
$gebruikersid = $_GET['user_id'];
if(!is_numeric($gebruikersid)) {
echo "Invoerfout!";
exit;
}
?>
De "!" voor is_numeric($gebruikersid) staat voor "niet", er staat dus: als is_numeric($gebruikersid) niet true is dan...
Het is slim om deze functies te 'verpakken' in andere functies zodat je niet steeds het hele 'if' ding moet typen:
PHP-code:
function requireNumericInput($key) {
$key = strtolower($key);
if(!isset($_REQUEST[$key]) {
echo "Invoerfout!";
exit;
}
$val = $_REQUEST[$key];
if(!is_numeric($val)) {
echo "Invoerfout!";
exit;
}
return $val;
}
function requireInput($key) {
$key = strtolower($key);
if(!isset($_REQUEST[$key]) {
echo "Invoerfout!";
exit;
}
return $_REQUEST[$key];
}
function numericInput($key,$default=0) {
$key = strtolower($key);
if(!isset($_REQUEST[$key]) {
return $default;
}
$val = $_REQUEST[$key];
if(!is_numeric($val)) {
return $default;
}
return $val;
}
function input($key,$default="") {
$key = strtolower($key);
if(!isset($_REQUEST[$key]) {
return $default;
}
$val = $_REQUEST[$key];
if(!is_numeric($val)) {
return $default;
}
return $val;
}
function nietleeg($key) {
if(!empty($key)) {
return "niet leeg";
}
else {
return "leeg";
}
}
/* En zo gebruik je deze functies (eventueel stop je de functies in een
apart bestand en include/require je ze */
$nummer = requireNumericInput('gebruikersid');
En zo kun je er nog wel meer bedenken. Door dit soort functies toe te passen is de code ook fijn leesbaar voor andere programmeurs (als er staat "requireNumericInput('id')" dan is voor iedereen duidelijk dat id een nummer moet zijn).
Invoer escapen
bewerkenNet zoals je in PHP bepaalde tekens moet escapen, moet invoer voor in een database ook ge'escaped' worden: dat alle invoer wordt gecontroleerd op tekens als " en '. Deze worden dan automatisch ge'escaped'(" wordt \", ' wordt \', enzovoort). Dat kan met functies zoals "addslashes", of voor mysql "mysqli_real_escape_string". Dit is handig, omdat je dan SQL injection kunt voorkomen (lees er meer over op de PHP website). Hieronder zien we een voorbeeld van gebruik van deze functies:
PHP-code:
<?php
$gebruikersid = $_GET['user_id'];
if(!is_numeric($gebruikersid)) {
echo "Invoerfout!";
exit;
}
?>
Het is slim om deze functies te 'verpakken' in andere functies zodat je niet steeds het hele 'if' ding moet typen:
PHP-code:
function requireNumericInput($key) {
$key = strtolower($key);
if(!isset($_REQUEST[$key]) {
echo "Invoerfout!";
exit;
}
$val = $_REQUEST[$key];
if(!is_numeric($val)) {
echo "Invoerfout!";
exit;
}
if(addslashes()) {
return stripslashes($val);
}
else {
return $val;
}
}
function requireInput($key) {
$key = strtolower($key);
if(!isset($_REQUEST[$key]) {
echo "Invoerfout!";
exit;
}
if(addslashes()) {
return stripslashes($_REQUEST[$key]);
}
else {
return $_REQUEST[$key];
}
}
function numericInput($key,$default=0) {
$key = strtolower($key);
if(!isset($_REQUEST[$key]) {
return $default;
}
$val = $_REQUEST[$key];
if(!is_numeric($val)) {
return $default;
}
if(addslashes()) {
return stripslashes($val);
}
else {
return $val;
}
}
function input($key,$default="") {
$key = strtolower($key);
if(!isset($_REQUEST[$key]) {
return $default;
}
$val = $_REQUEST[$key];
if(!is_numeric($val)) {
return $default;
}
if(addslashes()) {
return stripslashes($val);
}
else {
return $val;
}
}
/* En zo gebruik je deze functies (eventueel stop je de functies in een
apart bestand en include/require je ze */
$nummer = requireNumericInput('gebruikersid');
Nu krijg je gegarandeerd invoer die niet ge-escaped is. Let erop dat je bij het uitvoeren van SQL-queries altijd mysqli_real_escape_string gebruikt (of een andere functie die bij je database hoort, deze is specifiek voor MySQL)!