Tutorials
Selectief Geheugen
Hou onthoud je de waarde van selectboxen?
Pagina 1
Selectief Geheugen
[color=red]Voordat je deze tut leest; na het maken ervan ontdekte ik een mooiere manier, die ik op de laatste pagina van deze tut gezet heb. Als je evengoed de hele tut wilt lezen: be my guest :-)[/color]
Elke PHP programmeur moet wel eens een formulier maken. In zo'n formulier komen vaak zogenaamde selectboxen voor, waarbij de gebruiker een keuze kan maken uit een aantal opties. Een selectbox ziet er zo uit:
Je kunt van tevoren alvast een optie selecteren door er selected="selected" achter te zetten; in het voorbeeld hieronder wordt februari geselecteerd
Het probleem is vaak: hoe onthoud je de waarde van een selectbox als het formulier verzonden is? Stel dat de gebruiker een of ander veld niet goed heeft ingevuld. Dan wil je hem het formulier nog een keer laten zien. Het is dan belangrijk dat de dingen die al ingevuld waren niet opnieuw ingevuld hoeven te worden.
Elke PHP programmeur moet wel eens een formulier maken. In zo'n formulier komen vaak zogenaamde selectboxen voor, waarbij de gebruiker een keuze kan maken uit een aantal opties. Een selectbox ziet er zo uit:
<select name="maand">
<option value="januari">januari</option>
<option value="februari">februari</option>
<option value="maart">maart</option>
<!-- enzovoort -->
</select>
Je kunt van tevoren alvast een optie selecteren door er selected="selected" achter te zetten; in het voorbeeld hieronder wordt februari geselecteerd
<select name="maand">
<option value="januari">januari</option>
<option value="februari" selected="selected">februari</option>
<option value="maart">maart</option>
<!-- enzovoort -->
</select>
Het probleem is vaak: hoe onthoud je de waarde van een selectbox als het formulier verzonden is? Stel dat de gebruiker een of ander veld niet goed heeft ingevuld. Dan wil je hem het formulier nog een keer laten zien. Het is dan belangrijk dat de dingen die al ingevuld waren niet opnieuw ingevuld hoeven te worden.
Pagina 2
Waarde opvragen en de juiste optie selecteren
Stel dat je formulier er zo uit ziet:
Dan is na verzenden van het formulier de waarde van de selectbox op te vragen via:
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (isset ($_POST['maand'])) {
echo '<p>Gekozen maand: ' . $_POST['maand'] . '</p>';
}
}
?>
Om de waarde van de selectbox goed te zetten zou je dus bij elke <option> moeten checken of de waarde overeenkomt met $_POST['maand']:
Dit werkt ook wel, maar zal de eerste keer dat de pagina laadt een notice geven, als je tenminste je error_reporting op E_ALL hebt staan, zoals het hoort. Dan bestaat de variabele $_POST['maand'] niet omdat het formulier nog niet verzonden is. Je zult dan een notice krijgen: undefined index 'maand'
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<select name="maand">
<option value="januari">januari</option>
<option value="februari">februari</option>
<option value="maart">maart</option>
<!-- enzovoort -->
</select>
</form>
Dan is na verzenden van het formulier de waarde van de selectbox op te vragen via:
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (isset ($_POST['maand'])) {
echo '<p>Gekozen maand: ' . $_POST['maand'] . '</p>';
}
}
?>
Om de waarde van de selectbox goed te zetten zou je dus bij elke <option> moeten checken of de waarde overeenkomt met $_POST['maand']:
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<select name="maand">
<option value="januari"<?php if ($_POST['maand'] == 'januari') echo ' selected="selected"'; ?>>januari</option>
<option value="februari"<?php if ($_POST['maand'] == 'februari') echo ' selected="selected"'; ?>>februari</option>
<option value="maart"<?php if ($_POST['maand'] == 'maart') echo ' selected="selected"'; ?>>maart</option>
<!-- enzovoort -->
</select>
</form>
Dit werkt ook wel, maar zal de eerste keer dat de pagina laadt een notice geven, als je tenminste je error_reporting op E_ALL hebt staan, zoals het hoort. Dan bestaat de variabele $_POST['maand'] niet omdat het formulier nog niet verzonden is. Je zult dan een notice krijgen: undefined index 'maand'
Pagina 3
Een kortere manier zonder notices
Het probleem met de notices is op te lossen door:
<?php
// is het formulier al eens verzonden?
// dan bestaat er een variabele die $_POST['maand'] heet
if (isset ($_POST['maand'])) {
$maand = $_POST['maand'];
}
// formulier niet verzonden
// we kennen een standaardwaarde toe
else {
$maand = 'januari';
}
?>
en daarna in de selectbox zelf:
Dit werkt al beter, maar is nog steeds een beetje "brute force". In dit voorbeeld heb ik nog maar één selectbox, maar wat als er twee of drie selectboxen nodig zijn? Met knippen en plakken kom je natuurlijk een eind, maar je moet toch per <option> een aantal dingen met de hand aanpassen.
<?php
// is het formulier al eens verzonden?
// dan bestaat er een variabele die $_POST['maand'] heet
if (isset ($_POST['maand'])) {
$maand = $_POST['maand'];
}
// formulier niet verzonden
// we kennen een standaardwaarde toe
else {
$maand = 'januari';
}
?>
en daarna in de selectbox zelf:
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<select name="maand">
<option value="januari"<?php if ($maand == 'januari') echo ' selected="selected"'; ?>>januari</option>
<option value="februari"<?php if ($maand == 'februari') echo ' selected="selected"'; ?>>februari</option>
<option value="maart"<?php if ($maand == 'maart') echo ' selected="selected"'; ?>>maart</option>
<!-- enzovoort -->
</select>
</form>
Dit werkt al beter, maar is nog steeds een beetje "brute force". In dit voorbeeld heb ik nog maar één selectbox, maar wat als er twee of drie selectboxen nodig zijn? Met knippen en plakken kom je natuurlijk een eind, maar je moet toch per <option> een aantal dingen met de hand aanpassen.
Pagina 4
Een mooiere manier met associatieve arrays
Een associatieve array is een array met een string tussen de brackets in plaats van een getal. Bijvoorbeeld: $maanden['januari'], $maanden['februari']
Dit soort array kan ons heel goed van pas komen om het wat mooier te doen, zonder een if-constructie in elke <option> van onze selectbox.
We maken de volgende associatieve array aan:
<?php
$maanden = array (
'januari' => '', 'februari' => '', 'maart' => '', 'april' => '', 'mei' => '', 'juni' => '',
'juli' => '', 'augustus' => '', 'september' => '', 'oktober' => '', 'november' => '', 'december' => '');
?>
De array-keys zijn de maanden van het jaar en elk element bevat een lege string. Die geef ik in dit voorbeeld aan met twee enkele quotes: 'januari' => ''
$maanden['januari'] bevat dus eenvoudig een lege string. Als je hem naar het scherm zou echoën, zie je niets.
Na verzenden van het formulier is, zoals we net zagen, de waarde van de selectbox op te vragen via $_POST['maand']. Die gaan we gebruiken om het juiste element van onze associatieve array te vullen met de waarde ' selected="selected"'
<?php
// stel dat $_POST['maand'] de waarde 'februari' heeft
// dan zeggen we hieronder dus eigenlijk:
// $maanden['februari'] = ' selected="selected"';
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset ($_POST['maand'])) {
$maanden[$_POST['maand']] = ' selected="selected"';
}
?>
Alle elementen van de array $maanden zijn nu dus leeg, op ééntje na. Nu gaan we foreach gebruiken om de array te doorlopen:
<?php
echo '<select name="maanden">';
foreach ($maanden as $key => $value) {
echo '<option value="' . $key . '"' . $value . '>' . $key . '</option>';
}
echo '</select>';
?>
Bij de elf lege elementen in de array $maanden geeft dit als output:
Bij het ene gevulde element krijgen we:
Dit soort array kan ons heel goed van pas komen om het wat mooier te doen, zonder een if-constructie in elke <option> van onze selectbox.
We maken de volgende associatieve array aan:
<?php
$maanden = array (
'januari' => '', 'februari' => '', 'maart' => '', 'april' => '', 'mei' => '', 'juni' => '',
'juli' => '', 'augustus' => '', 'september' => '', 'oktober' => '', 'november' => '', 'december' => '');
?>
De array-keys zijn de maanden van het jaar en elk element bevat een lege string. Die geef ik in dit voorbeeld aan met twee enkele quotes: 'januari' => ''
$maanden['januari'] bevat dus eenvoudig een lege string. Als je hem naar het scherm zou echoën, zie je niets.
Na verzenden van het formulier is, zoals we net zagen, de waarde van de selectbox op te vragen via $_POST['maand']. Die gaan we gebruiken om het juiste element van onze associatieve array te vullen met de waarde ' selected="selected"'
<?php
// stel dat $_POST['maand'] de waarde 'februari' heeft
// dan zeggen we hieronder dus eigenlijk:
// $maanden['februari'] = ' selected="selected"';
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset ($_POST['maand'])) {
$maanden[$_POST['maand']] = ' selected="selected"';
}
?>
Alle elementen van de array $maanden zijn nu dus leeg, op ééntje na. Nu gaan we foreach gebruiken om de array te doorlopen:
<?php
echo '<select name="maanden">';
foreach ($maanden as $key => $value) {
echo '<option value="' . $key . '"' . $value . '>' . $key . '</option>';
}
echo '</select>';
?>
Bij de elf lege elementen in de array $maanden geeft dit als output:
<option value="maandnaam">maandnaam</option>
Bij het ene gevulde element krijgen we:
<option value="maandnaam" selected="selected">maandnaam</option>
Pagina 5
Meer dan 1 selectbox: automatisch genereren
Als we van dit verhaal een functie kunnen maken, kunnen we het automatiseren. Gelukkig blijkt dat helemaal niet moeilijk:
<?php
// $name is de naam van de selectbox
// $options is de naam van de associatieve array met de waardes er in
function make_select ($name, $options) {
echo '<select name="' . $name . '">';
foreach ($options as $key => $value) {
echo '<option value="' . $key . '"' . $value . '>' . $key . '</option>';
}
echo '</select>';
}
?>
Hieronder een compleet werkend voorbeeld met twee selectboxen (maanden en jaren). Er zit een kleine extra functie bij die tabs en eventueel een newline plaatst voordat je iets echoot. Zo ziet je broncode er ook nog een beetje netjes uit.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Selective Memory</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<form action="index.php" method="post">
<p>
<input type="submit" value="verzenden">
</p>
</form>
</body>
</html>
[/code]
<?php
// $name is de naam van de selectbox
// $options is de naam van de associatieve array met de waardes er in
function make_select ($name, $options) {
echo '<select name="' . $name . '">';
foreach ($options as $key => $value) {
echo '<option value="' . $key . '"' . $value . '>' . $key . '</option>';
}
echo '</select>';
}
?>
Hieronder een compleet werkend voorbeeld met twee selectboxen (maanden en jaren). Er zit een kleine extra functie bij die tabs en eventueel een newline plaatst voordat je iets echoot. Zo ziet je broncode er ook nog een beetje netjes uit.
[code]
<?php
error_reporting (E_ALL);
function t($n_tabs, $newline = false) {
if ($newline) echo "\n";
for ($i = 0; $i < $n_tabs; $i++) {
echo "\t";
}
}
function make_select ($name, $options) {
t (3, true);
echo '<select name="' . $name . '">';
foreach ($options as $key => $value) {
t (4, true);
echo '<option value="' . $key . '"' . $value . '>' . $key . '</option>';
}
t (3, true);
echo '</select>';
}
$maanden = array (
'januari' => '', 'februari' => '', 'maart' => '', 'april' => '', 'mei' => '', 'juni' => '',
'juli' => '', 'augustus' => '', 'september' => '', 'oktober' => '', 'november' => '', 'december' => '');
$jaren = array (
'2006' => '', '2007' => '', '2008' => '', '2009' => '', '2010' => '', '2011' => '',
'2012' => '', '2013' => '', '2014' => '', '2015' => '', '2016' => '', '2017' => '');
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset ($_POST['maand']) && isset ($_POST['jaar'])) {
$maanden[$_POST['maand']] = ' selected="selected"';
$jaren[$_POST['jaar']] = ' selected="selected"';
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Selective Memory</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<form action="index.php" method="post">
<p>
<?php
make_select ('maand', $maanden);
make_select ('jaar', $jaren);
?>
<input type="submit" value="verzenden">
</p>
</form>
</body>
</html>
[/code]
Pagina 6
Eureka: multidimensionale array!
Dinsdagochtend, 1 augustus 2006
[color=red]Uitbreiding op de tut.
Dit verhaal liet me toch niet los en ik geloof dat ik een nog mooiere manier gevonden heb :-) Ik post hem hieronder:[/color]
Stel dat je een selectbox hebt als deze:
Eigenlijk bestaat een <select> uit niets anders dan twee arrays; de values en de options. Soms zijn ze gelijk, maar vaak ook niet.
Als ik nu eens een multidimensionale array zou maken, die er zo uitziet:
dan hoef ik na het verzenden van het formulier alleen maar te kijken wat de waarde is van $_POST['fruit']. Is die
waarde bijvoorbeeld '2', dan doe ik $fruit[2]['selected'] = ' selected="selected"';
Op deze manier kan ik een <select> genereren aan de hand van twee argumenten: een naam, en de mulitdimensionale array
die ik bijwerk aan de hand van de POST variabelen!
Eén en ander resulteerde in de volgende code:
Tot zover deze uitbreiding. Ik hoop dat jullie er iets aan hebben!
Happy PHP-ing!
Jan Koehoorn
[color=red]Uitbreiding op de tut.
Dit verhaal liet me toch niet los en ik geloof dat ik een nog mooiere manier gevonden heb :-) Ik post hem hieronder:[/color]
Stel dat je een selectbox hebt als deze:
<select name="fruit">
<option value="1">appel</option>
<option value="2">peer</option>
<option value="3">banaan</option>
</select>
Eigenlijk bestaat een <select> uit niets anders dan twee arrays; de values en de options. Soms zijn ze gelijk, maar vaak ook niet.
Als ik nu eens een multidimensionale array zou maken, die er zo uitziet:
$fruit[1]['selected'] = '';
$fruit[1]['option'] = 'appel';
$fruit[2]['selected'] = '';
$fruit[2]['option'] = 'peer';
$fruit[3]['selected'] = '';
$fruit[3]['option'] = 'banaan';
dan hoef ik na het verzenden van het formulier alleen maar te kijken wat de waarde is van $_POST['fruit']. Is die
waarde bijvoorbeeld '2', dan doe ik $fruit[2]['selected'] = ' selected="selected"';
Op deze manier kan ik een <select> genereren aan de hand van twee argumenten: een naam, en de mulitdimensionale array
die ik bijwerk aan de hand van de POST variabelen!
Eén en ander resulteerde in de volgende code:
<?php
ini_set('display_errors', 1);
error_reporting (E_ALL);
// plaats een aantal tabs en eventueel een newline
function t($n_tabs, $newline = false) {
if ($newline) echo "\n";
for ($i = 0; $i < $n_tabs; $i++) {
echo "\t";
}
}
// maak een multidimensionale array aan
// er zou nog een check bij moeten of $values en $options wel even lang zijn
function set_multi_array ($values, $options) {
$multi_array = array ();
$n = count ($values);
for ($i = 0; $i < $n; $i++) {
$multi_array[$values[$i]]['selected'] = '';
$multi_array[$values[$i]]['option'] = $options[$i];
}
return $multi_array;
}
// genereer een <select> aan de hand van een multidimensionale array
function make_select ($name, $multi_array) {
t (3, true);
echo '<label for="' . $name . '">' . $name . ':</label>';
echo '<select id="' . $name . '" name="' . $name . '">';
foreach ($multi_array as $key => $value) {
t (4, true);
echo '<option value="' . $key . '"' . $value['selected'] . '>' . $value['option'] . '</option>';
}
t (3, true);
echo '</select>';
t (2, true);
}
// nu alle functies werken, instantieren we een aantal selects
// deze select heeft als values de getallen 1 t/m 5 en als options de strings 'dammen', 'schaken', enz
$hobbies_values = range (1, 5);
$hobbies_options = array ('dammen','schaken','bridge','poker','judo');
$hobbies = set_multi_array ($hobbies_values, $hobbies_options);
// deze select heeft als values de getallen 1 t/m 12 en als options de strings 'Januari', 'Februari', enz
$maanden_values = range (1, 12);
$maanden_options = array ('Januari','Februari','Maart','April','Mei','Juni','Juli','Augustus','September','Oktober','November','December');
$maanden = set_multi_array ($maanden_values, $maanden_options);
// deze select heeft zowel voor de values als de options de getallen 1 t/m 31, dus krijgt hij gewoon twee keer dezelfde array mee!
$dagen_values = range (1, 31);
$dagen = set_multi_array ($dagen_values, $dagen_values);
// deze select heeft zowel voor de values als de options de getallen 2000 t/m 2050, dus krijgt hij gewoon twee keer dezelfde array mee!
$jaren_values = range (2000, 2050);
$jaren = set_multi_array ($jaren_values, $jaren_values);
if (isset ($_POST['hobbies'])) {
// de POST waarden in de multidimensionale array verwerken...
$hobbies[$_POST['hobbies']]['selected'] = ' selected="selected"';
$maanden[$_POST['maanden']]['selected'] = ' selected="selected"';
$dagen[$_POST['dagen']]['selected'] = ' selected="selected"';
$jaren[$_POST['jaren']]['selected'] = ' selected="selected"';
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Selective Memory</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
p, label, select, option {
font: 12px verdana;
color: #66f;
}
</style>
</head>
<body>
<form action="index.php" method="post">
<p>
<?php
// en hier simpel de select genereren
make_select ('hobbies', $hobbies);
make_select ('maanden', $maanden);
make_select ('dagen', $dagen);
make_select ('jaren', $jaren);
?>
<input type="submit" value="verzenden">
</p>
</form>
</body>
</html>
Tot zover deze uitbreiding. Ik hoop dat jullie er iets aan hebben!
Happy PHP-ing!
Jan Koehoorn
Reacties
0