Tutorials

ENUM to SELECT

Hoe je van een MySQL enum een selectbox kunt maken

Pagina 1

Inleiding

ENUM TO SELECT

Voor wie het enum veld niet kent, even een korte uitleg:
een enum veld in je MySQL database kun je gebruiken om rijtjes waarden op te slaan die vaak voorkomen. Laatst was ik bezig met een online-redactie voor een tijdschrift en daar hebben artikelen een aantal statussen: "binnengekomen", "goedgekeurd", "afgewezen", "reserve", enz.
Of denk aan orderstatussen, als je iets online bestelt: "ontvangen", "bevestigd", "betaald", "verzonden".

Als users zelf met de database aan de gang gaan, moeten ze die waardes natuurlijk kunnen invullen. Nu kun je daarvoor een input text maken, maar da's riskant, want dan weet je nooit wat ze gaan doen. Een selectbox is veel logischer omdat je dan zeker weet dat er geen vreemde waardes ingevuld kunnen worden.

Nou was ik dapper op de volgende manier begonnen met dat redactiescript:

<select id="status" name="status">
<option value="binnengekomen">binnengekomen</option>
<option value="goedgekeurd">goedgekeurd</option>
<option value="afgewezen">afgewezen</option>
<option value="reserve">reserve</option>
</select>

Dus gewoon "hardcoded", zoals ik dat altijd maar noem, maar je raadt het al; ineens moesten er een paar statussen bij: "vertaald", "nog niet vertaald" en "nog niet binnen". Nou had ik nog maar één pagina met zo'n selectbox, maar het zette me toch aan het denken. Stel dat ik nog meer pagina's nodig had, of stel dat ik nog meer enum-velden ging krijgen?
Pagina 2

PHP versus MySQL

Er zijn wel PHP functies om informatie over een type veld te krijgen, zoals mysql_field_type () maar die leveren niet de info die ik wil hebben. Die vertelt me wel DAT het een enum is, maar niet WAT er in die enum aan mogelijke waarden zit.

Gelukkig biedt MySQL uitkomst. Met het commando DESCRIBE, of SHOW COLUMNS FROM kun je informatie opvragen over kolommen in je db. De syntax verschilt enigszins (geen idee waarom). Die van DESCRIBE is korter en zonder quotes.

DESCRIBE artikelen status
+------+---------------------------------------+----+----+---------+-----+
|Field  |Type                                           |Null |Key|Default  |Extra|
+------+---------------------------------------+----+----+---------+-----+
|status|enum('nog niet binnen','nog niet ...|      |      |bewaren|       |
+------+---------------------------------------+----+----+---------+-----+

of zo (geeft precies hetzelfde resultaat):
SHOW COLUMNS FROM artikelen LIKE 'status'
+------+---------------------------------------+----+----+---------+-----+
|Field  |Type                                           |Null |Key|Default  |Extra|
+------+---------------------------------------+----+----+---------+-----+
|status|enum('nog niet binnen','nog niet ...|      |      |bewaren|       |
+------+---------------------------------------+----+----+---------+-----+

Kijk, da's interessant! Bij 'Field' krijg ik keurig de naam van mijn enum veld en bij 'Type' de inhoud :-) Nu kan ik met PHP aan de gang. De code voor verbinden met en selecteren van de database sla ik hier even over:

<?php
// query opstellen
$sql = "DESCRIBE artikelen status";
if (!($res = mysql_query ($sql))) {
trigger_error (mysql_error ());
}
else {
// we weten zeker dat het om 1 record
// gaat, dus geen while loop nodig
$obj = mysql_fetch_object ($res);
$name = $obj->Field;
$enums = $obj->Type;
}
?>
Pagina 3

Regex en Explode

In mijn voorbeeld bevat $enums nu de volgende (string)waarde:
enum('nog niet binnen','nog niet af','nog te vertalen','geplaatst','afgekeurd','bewaren')

Da's natuurlijk schitterend, maar ik wil er een array van maken. Eerst ga ik de string "opschonen" met een regular expression.

<?php
// string opschonen
$enums = eregi_replace ('(enum\(|\)|\')', '', $enums);
?>

Regular expressions zijn een hoofdstuk apart, dus deze ga ik niet uitleggen, maar hierna hou ik over:
nog niet binnen,nog niet af,nog te vertalen,geplaatst,afgekeurd,bewaren

Aan het begin is enum( verwijderd, aan het eind ), en alle enkele quotes zijn ook weg. Nu is het verder een eitje:

<?php
// array maken
$enums = explode (',', $enums);
$n = count ($enums);
?>

De naam voor de selectbox hadden we al opgehaald met $name = $obj->Field.
Hier de code voor het maken van een selectbox met options.

<?php
// selectbox maken
echo '<label for="' . $name . '">' . $name . ':</label>';
echo '<select id="' . $name . '" name="' . $name . '" class="small">';
for ($i = 0; $i < $n; $i++) {
echo '<option value="' . $enums[$i] . '">' . $enums[$i] . '</option>';
}
echo '</select>';
?>
Pagina 4

Functie

Nou is het bij selectboxen wel prettig als je de selectie kunt onthouden na bijvoorbeeld een page refresh. We maken er dus een functie van die een optioneel argument meekrijgt:

<?php
function enum_to_select ($selected = false)
?>

Nu kun je een waarde meegeven (hoeft niet) waarna de juiste option geselecteerd wordt. Na een submit van het formulier waar deze selectbox in staat, kun je de waarde bijv opvragen met $_POST['status']. Ongeveer zo:

<?php
// form verzonden?
if (isset ($_POST['status'])) {
enum_to_select ($_POST['status']);
}
else {
enum_to_select ();
}
?>

In de functie zelf doe je dan dit:

<?php
// selectbox maken
echo '<label for="' . $name . '">' . $name . ':</label>';
echo '<select id="' . $name . '" name="' . $name . '" class="small">';
for ($i = 0; $i < $n; $i++) {
if ($selected == $enums[$i]) {
echo '<option value="' . $enums[$i] . '" selected>' . $enums[$i] . '</option>';
}
else {
echo '<option value="' . $enums[$i] . '">' . $enums[$i] . '</option>';
}
}
echo '</select>';
?>
Pagina 5

Tot slot

Tot slot hier nog de hele code:

<?php
// functie in zijn geheel
function enum_to_select ($selected = false) {
$sql = "DESCRIBE artikelen status";
if (!($res = mysql_query ($sql))) {
trigger_error (mysql_error ());
}
else {
$obj = mysql_fetch_object ($res);
$name = $obj->Field;
$enums = $obj->Type;
$enums = eregi_replace ('(enum\(|\)|\')', '', $enums);
$enums = explode (',', $enums);
$n = count ($enums);

echo '<label for="' . $name . '">' . $name . ':</label>';
echo '<select id="' . $name . '" name="' . $name . '" class="small">';
for ($i = 0; $i < $n; $i++) {
if ($selected == $enums[$i]) {
echo '<option value="' . $enums[$i] . '" selected>' . $enums[$i] . '</option>';
}
else {
echo '<option value="' . $enums[$i] . '">' . $enums[$i] . '</option>';
}
}
echo '</select>';
}
}
?>

todo: (lijst kan langer worden nav reacties)
- De functie zou nog algemener kunnen als ook de tabelnaam en de kolomnaam als argumenten meegegeven kunnen worden.
- foreach gebruiken ipv for met count

Tot zover deze tut. Ik hoop het vooral voor beginnende PHP-ers een beetje te volgen was. Happy PHP-ing!

Jan Koehoorn

Reacties

0
Nog geen reacties.