Je ziet dit bericht omdat de EU dat een goed idee vindt. Deze website maakt gebruik van cookies van Google voor het tonen van advertenties en het bijhouden van bezoekersstatistieken. Google kan hiermee je surfgedrag volgen. Zie voor meer informatie het privacybeleid van Google. Via Your Online Choices kun tracking cookies van advertentiebedrijven blokkeren. Deze melding verbergen.

13 Lussen

Lussen worden gebruikt om bepaalde handelingen meerdere keren achter elkaar uit te voeren. Lussen worden veelvuldig gebruikt in combinatie met MySQL (waarover later meer) voor situaties als "voor iedere rij in de tabel, doe dit". Ook op andere plaatsen kunnen lussen handig zijn, zoals we zullen zien in dit hoofdstuk. PHP kent meerdere soorten lussen. Hier komen while, for en foreach aan de orde.

Theorie

Een lus is een stuk code dat onder bepaalde voorwaarden uitgevoerd wordt. Zolang de voorwaarde waar (TRUE) is, wordt de code in de lus steeds opnieuw uitgevoerd. Als in de lus een variabele wordt aangepast, dan heeft deze variabele de nieuwe waarde bij de volgende keer dat de lus wordt uitgevoerd. Totdat de voorwaarde van de lus niet meer waar is. De voorwaarde moet zorgvuldig worden gekozen; een foutje kan er voor zorgen dat de lus niet meer stopt. Mocht dat toch gebeuren, dan zorgt PHP dat het script (standaard) na 30 seconden toch wordt gestopt.

De verschillende soorten lussen in PHP lijken op elkaar, alleen is steeds de voorwaarde anders opgebouwd. De while-lus is het meest eenvoudig, de for-lus is wat ingewikkelder en de foreach-lus is er speciaal voor het werken met arrays.

While

De while-lus is de eenvoudigste lus in PHP. De basisvorm is hieronder afgebeeld en kan worden gelezen als zolang de voorwaarde waar is, blijf steeds opnieuw de opdracht uitvoeren. De voorwaarde wordt steeds bekeken aan het begin van de lus. Het kan dus dat de lus nooit wordt uitgevoerd, als de voorwaarde aan het begin al FALSE is.

while (voorwaarde) {
    opdracht;
}

Laten we een eenvoudig voorbeeld bekijken. We willen vijf keer de tekst "Welkom op mijn website." achter elkaar weergeven (geen idee waarom, maar toch). Als while-lus ziet dat er als volgt uit:

<?php
$i
= 0;
$a = 5;
while (
$i < $a) {
    echo
'Welkom op mijn website.';
    
$i = $i + 1;
}
?>

Er worden twee hulpvariabelen gebruikt. $i (de lus-teller) om bij te houden hoe vaak de lus is uitgevoerd. Deze zetten we op nul. En we gebruiken $a om het aantal keer dat we de lus willen uitvoeren op te geven. Deze zetten we dus op vijf. De voorwaarde van de lus wordt dan "zolang $i kleiner is dan $a", ofwel ($i < $a). Binnen de accolades { en } van de while-lus geven we op wat er vijf keer moet gebeuren: het weergeven van de tekst. Belangrijk is om binnen de lus ook steeds $i met één op te hogen. Anders blijft $i steeds nul en loopt de lus oneindig door! We doen dit met $i = $i + 1;.

Dit is wat er met de voorwaarde gebeurt iedere keer dat de lus wordt uitgevoerd:

  1. (0 < 5) geeft TRUE, dus de lus wordt voor de 1e keer uitgevoerd;
  2. (1 < 5) geeft TRUE, dus de lus wordt voor de 2e keer uitgevoerd;
  3. (2 < 5) geeft TRUE, dus de lus wordt voor de 3e keer uitgevoerd;
  4. (3 < 5) geeft TRUE, dus de lus wordt voor de 4e keer uitgevoerd;
  5. (4 < 5) geeft TRUE, dus de lus wordt voor de 5e keer uitgevoerd;
  6. (5 < 5) geeft FALSE, dus de lus wordt niet meer uitgevoerd, PHP gaat verder met de rest van het script na de lus.

$i++

In plaats van $i = $i + 1; kunnen we dit ook korter schrijven als $i++;. De ++ betekent tel één bij de variabele op en kan ook bij variabelen met een andere naam dan $i gebruikt worden. Dit is niet verplicht, maar wordt wel vaak gebruikt en is dus goed om te weten wat het betekent. Omdat het zoveel gebruikt wordt zullen we het in dit boek voortaan ook toepassen. Met $i++; komt het vorige voorbeeld er als volgt uit te zien:

<?php
$i
= 0;
$a = 5;
while (
$i < $a) {
    echo
'Welkom op mijn website.';
    
$i++;
}
?>

Array

Lussen kunnen bij uitstek ook gebruikt worden in combinatie met array's. Bijvoorbeeld om alle waarden uit een array weer te geven. Veronderstel de volgende array met alle maanden van het jaar:

<?php
$maanden
= array ('Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December');
?>

We willen deze array gebruiken om het volgende lijstje te maken:

Maand 1 is Januari.
Maand 2 is Februari.
Maand 3 is Maart.
Maand 4 is April.
Maand 5 is Mei.
Maand 6 is Juni.
Maand 7 is Juli.
Maand 8 is Augustus.
Maand 9 is September.
Maand 10 is Oktober.
Maand 11 is November.
Maand 12 is December.

Dat kan natuurlijk handmatig zoals hieronder is weergegeven, maar erg efficiënt is dat niet.

<?php
echo 'Maand 1 is '.$maanden[0].'.<br />';
echo
'Maand 2 is '.$maanden[1].'.<br />';
echo
'Maand 3 is '.$maanden[2].'.<br />';
echo
'Maand 4 is '.$maanden[3].'.<br />';
echo
'Maand 5 is '.$maanden[4].'.<br />';
echo
'Maand 6 is '.$maanden[5].'.<br />';
echo
'Maand 7 is '.$maanden[6].'.<br />';
echo
'Maand 8 is '.$maanden[7].'.<br />';
echo
'Maand 9 is '.$maanden[8].'.<br />';
echo
'Maand 10 is '.$maanden[9].'.<br />';
echo
'Maand 11 is '.$maanden[10].'.<br />';
echo
'Maand 12 is '.$maanden[11].'.<br />';
?>

We kunnen hiervoor natuurlijk ook een while-lus gebruiken, vergelijkbaar met het eerdere voorbeeld.

<?php
$i
= 0;
$a = count($maanden);
while (
$i < $a) {
    echo
'Maand ';
    echo
$i + 1;
    echo
' is ';
    echo
$maanden[$i];
    echo
'.<br />';
    
$i++;
}
?>

Net als in het vorige voorbeeld begint $i weer bij nul. Voor $a vullen we het aantal maanden in. Dit is uiteraard 12, maar stel dat we dit niet weten, dan kunnen we ook aan PHP vragen hoeveel elementen er in een array zitten met behulp van de functie count().

int count ( mixed $array_or_countable )

Deze functie geeft van een array (of iets anders wat geteld kan worden) uit hoeveel elementen deze bestaat. Voor onze array met maanden zal deze functie dus 12 als resultaat geven. De voorwaarde van de lus is wederom ($i < $a), dus de lus wordt uitgevoerd zo lang dat $i kleiner is dan het aantal elementen in de maanden-array (dat we voor het gemak hebben opgeslagen in $a).

Binnen de while-lus verhogen $i niet alleen steeds met één via $i++, maar gebruiken we $i ook om het nummer van de maand weer te geven en de naam van de maand uit de array te halen. In de array van maanden zijn de sleutels automatisch genummerd van 0 tot 11. Dat komt goed uit, want $i begint ook bij 0. Met $maanden[$i] kunnen we dus bij iedere herhaling van de lus de juiste maand uit de array ophalen. Voor het weergeven van het nummer van de maand is het weer niet handig om met 0 te beginnen (want januari is maand 1 en niet maand 0), dus moeten we 1 bij $i optellen om bij het juiste getal uit te komen. Let op dat we hier niet $i++ gebruiken, omdat we $i nog onveranderd nodig hebben voor het ophalen van de juiste maand uit de array. $i++ past de waarde van de variabele direct aan, terwijl echo $i + 1; alleen het resultaat van de som laat zien, zonder $i te veranderen.

For

De for-lus is de moeilijkste lus in PHP. In principe is er weinig verschil met een while-lus, behalve in de manier van opschrijven. De for-lus heeft als voordeel dat de startwaarde van de lus-teller, de voorwaarde en het verhogen van de lus-teller bij elkaar worden opgeschreven, waardoor dit makkelijker is terug te vinden. Verder is de for-lus marginaal sneller in uitvoering, maar met de krachtige computers van tegenwoordig hoeft dat geen reden meer te zijn om een for-lus te gebruiken.

De structuur van de for-lus ziet er als volgt uit:

for (start; voorwaarde; ophoging) {
    opdracht;
}

Onze while-lus van het begin is als volgt als een for-lus te schrijven:

<?php
for ($i = 0; $i < 5; $i++) {
    echo
'Welkom op mijn website.';
}
?>

De verschillen zijn dat $i = 0 niet meer apart staat, maar als eerste argument van de lus. Daarna komt de voorwaarde $i < 5. Er wordt geen gebruik meer gemaakt van hulpvariabele $a, in plaats daarvan is het aantal herhalingen van de lus direct opgeschreven. Het derde argument is het verhogen van de lus-teller. Deze wordt aan het eind van iedere herhaling uitgevoerd. $i++ staat nu hier en niet meer aan het einde van de lus.

Het resultaat is hetzelfde als voorheen, dus al met al is het vooral een kortere manier van opschrijven. Ook in geval van de array met maanden kunnen we een for-lus toepassen. De verschillen zijn hetzelfde.

<?php
for ($i = 0; $i < count($maanden); $i++) {
    echo
'Maand ';
    echo
$i + 1;
    echo
' is ';
    echo
$maanden[$i];
    echo
'.<br />';
}
?>

Foreach

De foreach-lus is een speciale for-lus voor het gebruik met array's. In dit geval is er geen lus-teller, maar wordt de opgegeven array element voor element doorgelopen. Het belangrijkste verschil is dat we niet hoeven weten of opzoeken hoeveel elementen de array heeft. Dat doet PHP voor ons. De structuur van de foreach-lus ziet er als volgt uit:

foreach ($array as $key => $value) {
    opdracht;
}

De argumenten van foreach zijn dus de array die doorlopen moet worden. Voor iedere herhaling van de lus wordt steeds het eerstvolgende element in de array gebruikt. De sleutel van het element wordt in $key geplaatst en de bijbehorende waarde in $value. $key en $value zijn dus anders bij iedere herhaling van de array. In plaats van $key en $value kunnen ook andere variabelen worden gekozen. Als de waarde van de sleutel niet van belang is, kan dit argument worden weggelaten:

foreach ($array as $value) {
    opdracht;
}

De while-lus of for-lus met de array van maanden kan ook als foreach-lus worden geschreven:

<?php
foreach ($maanden as $i => $maand) {
    echo
'Maand ';
    echo
$i + 1;
    echo
' is ';
    echo
$maand;
    echo
'.<br />';
}
?>

In dit geval gebruiken we wel de sleutels van de array, om het nummer van de maand weer te geven. Deze wordt voor iedere herhaling opgeslagen in $i. De naam van de maand komt uit de waarde van ieder element in de array. Voor iedere herhaling wordt deze opgeslagen in $maand. Merk op dat count($maanden) helemaal is verdwenen. Deze hebben we niet meer nodig.

Break

Soms kan het handig zijn om doorlopen van de lus te stoppen voordat vooraf bedoelde herhalingen is bereikt. Bijvoorbeeld omdat het simpelweg niet meer nodig is om de rest te doorlopen. Dit kan met break;. Als voorbeeld bekijken we de functie in_array(). Deze kijkt of een gegeven waarde in een array voorkomt.   

bool in_array ( mixed $needle , array $haystack )

De functie zoekt een naald in een hooiberg en kijkt of de waarde $needle voorkomt in de array $haystack. Om te controleren of de maand 'Maart' voorkomt in de array met maanden, kunnen we de functie als volgt gebruiken:

<?php
$needle
= 'Maart';
if (
in_array($needle, $maanden)) {
    echo
'waarde bestaat';
}
?>

In plaats van de functie in_array() te gebruiken kunnen we dit met behulp van een lus ook zelf doen. Hierbij is break; handig om niet verder te zoeken dan nodig is.

<?php
$needle
= 'Maart';
foreach(
$maanden as $maand) {
    if (
$needle == $maand) {
        echo
'waarde bestaat';
        break;
    }
}
?>

In dit geval zorgt break; ervoor dat het herhalen van de lus stopt zodra 'Maart' is gevonden en de tekst waarde bestaat is weergegeven. Het heeft immers geen nut om na het vinden van Maart nog verder te kijken in April t/m December. We wilden immers alleen weten of Maart in de array voorkomt, we hebben niet gevraagd hoe vaak Maart voorkomt. Dus als Maart gevonden is, is het niet meer nuttig om naar de rest te kijken.

Zelftest

  1. Wat is de lus-teller?
    1. Een variabele die het aantal lussen in een script bevat.
    2. Een variabele die aangeeft hoe vaak een lus wordt uitgevoerd.
    3. Een variabele die iedere keer wordt opgehoogd.
    4. De naam van $i++.
  2. Wat is de juiste volgorde van argumenten van een for-lus?
    1. start, voorwaarde, ophoging
    2. voorwaarde, start, ophoging
    3. start, ophoging, voorwaarde
    4. ophoging, voorwaarde, start
  3. Welke van onderstaande stellingen is/zijn waar?
    I             Een while-lus is beter dan een for-lus;
    II            Een foreach-lus heeft geen lus-teller.
    1. Beide stellingen zijn onwaar.
    2. Alleen stelling I is waar.
    3. Alleen stelling II is waar.
    4. Beide stellingen zijn waar.
  4. Met break; ...
    1. ...kan worden aangegeven dat het script voor een bepaalde tijd gepauzeerd moet worden.
    2. ...kan het uitvoeren van een lus op ieder gewenst moment worden gestopt.
    3. ...wordt aangegeven dat er iets stuk is.
    4. ...kan het herhalen van een lus op ieder gewenst moment worden gestopt.

Antwoorden zelftest

Antwoorden

  1. c
  2. a
  3. c
  4. b

Oefening: drop-down menu

HTML-formulieren kunnen drop-down menu's bevatten. De algemene opbouw van zo'n formulier is als volgt:

<select name="veldnaam">
    <option value="waarde1">tekst1</option>
    <option value="waarde2">tekst2</option>
    <option value="waarde3">tekst3</option>
</select>

Aan een option kan eventueel nog het attribuut selected="selected" worden toegevoegd om iets anders dan de bovenste optie standaard te selecteren. In deze oefening maken we een drop-down menu waarbij iemand zijn geboortejaar kan selecteren.

Opdracht 1

Maak een drop-down menu met de jaartallen 1900 tot en met het huidige jaar. Het huidige jaar kan worden opgevraagd met de PHP-functie date('Y'). We gaan nu niet in op de werking hiervan, maar hiermee kan worden voorkomen dat het formulier ieder jaar moet worden aangepast. Vul date('Y') dus in plaats van 2017 in.

Opdracht 2

Pas het drop-down menu aan, zodat de jaartallen in aflopende volgorde worden weergegeven en dat de geboortejaren voor mensen jonger dan 18 worden weggelaten.

Opdracht 3

Plaats het aangepaste drop-down menu in een werkend formulier. Na het verzenden van het formulier wordt hetzelfde formulier weergegeven, waarbij het geselecteerde jaar ook automatisch wordt geselecteerd.

Uitwerking opdracht

Uitwerking

opdracht1.php

<?php
echo '<select name="jaar">';
for (
$j = 1900; $j <= date('Y'); $j++) {
    echo
'<option value="' . $j . '">' . $j . '</option>';
}
echo
'</select>';
?>

opdracht2.php

<?php
echo '<select name="jaar">';
for (
$j = date('Y') - 17; $j >= 1900; $j--) {
    echo
'<option value="' . $j . '">' . $j . '</option>';
}
echo
'</select>';
?>

opdracht3.php

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Selecteer geboortejaar</title>
</head>
<body>
<form method="post">
<select name="jaar">
<?php
for ($j = date('Y') - 17; $j >= 1900; $j--) {
    echo
'<option value="' . $j . '"';
    if (
$_POST['jaar'] == $j) echo ' selected="selected"';
    echo
'>' . $j . '</option>';
}
?>
</select>
<input type="submit" value="Verzenden">
</form>
</body>
</html>