Recursieve functies in PHP

  1. Inleiding
  2. Wat is recursie?
  3. Recursie toegepast
  4. Directories uitlezen met behulp van recursie
  5. Slotwoord en referenties
  6. Reacties op deze tutorial

Directories uitlezen met behulp van recursie

Nu we de basis van recursie behandeld hebben, kunnen we kijken naar een mooier voorbeeld van recursie. Hoewel er sinds PHP 5 enkele functies zijn die het uitlezen van een directory in een keer voor je kunnen doen, zal ik hier een recursieve functie laten zien die dat ook doet.

Het uitlezen van een bepaalde map op zich zal geen probleem zijn. Een combinatie van opendir() en readdir() levert het gewenste resultaat.

Voor de voorbeelden gebruik ik de volgende bestandsstructuur:
Code
1
2
3
4
5
6
7
8
9
gebruikers/
gebruikers/a
gebruikers/a/arend.txt
gebruikers/a/arjan.txt
gebruikers/gebruikers.txt
gebruikers/p
gebruikers/p/eigenschappen
gebruikers/p/eigenschappen/file.txt
gebruikers/p/piet.txt


Voorbeeld 8: Uitlezen van een map
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
function leesUit($path)
{
    if(
$dir = @opendir($path))
    {
        while((
$file readdir($dir)) !== FALSE)
        {
            if(
$file != '.' && $file != '..')
            {
                
$output[] = $file;
            }
        }
        
closedir($dir);
    }
    return isset(
$output) ? $output FALSE;
}

$map 'gebruikers';
echo 
'<pre>';
print_r(leesUit($map));
echo 
'</pre>';
?>

De functie kijkt allereerst of het opgegeven pad te openen is als directory. Zoja, dan wordt de readdir() functie gebruikt om de map uit te lezen en de bestanden in de $output array te zetten. Vervolgens wordt de directory weer gesloten en wordt bepaald wat er geretourneerd moet worden. Als de functie succesvol verlopen is zal $output geretourneerd worden en in het andere geval FALSE.

Het resultaat van dit script is als volgt:
Code
1
2
3
4
5
6
Array
(
    [0] => a
    [1] => gebruikers.txt
    [2] => p
)

We zien dat de map 'gebruikers' netjes uitgelezen worden en alle aanwezige mappen en bestanden gegeven worden. Alleen zien we in de bestandsstructuur dat de mappen 'a' en 'p' ook nog bestanden en mappen bevatten.

Voor het weergeven van deze bestanden en mappen kunnen we een recursief onderdeel in de functie aanbrengen. Op een bepaalde moment binnen leesUit() functie zullen we diezelfde leesUit() functie aanroepen.

Voorbeeld 9: Volledige directory uitlezen met behulp van recursie
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
function leesUit($path)
{
    if(
$dir = @opendir($path))
    {
        while((
$file readdir($dir)) !== FALSE)
        {
            if(
is_dir($path.'/'.$file) && $file != '.' && $file != '..')
            {
                
$output[$file] = leesUit($path.'/'.$file);
            }            
            elseif(
$file != '.' && $file != '..')
            {
                
$output[] = $file;
            }
        }
        
closedir($dir);
    }
    return isset(
$output) ? $output FALSE;
}

$map 'gebruikers';
echo 
'<pre>';
print_r(leesUit($map));
echo 
'</pre>';
?>

Dit is dan het resultaat:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Array
(
    [a] => Array
        (
            [0] => arend.txt
            [1] => arjan.txt
        )

    [0] => gebruikers.txt
    [p] => Array
        (
            [eigenschappen] => Array
                (
                    [0] => file.txt
                )

            [0] => piet.txt
        )

)

We zien dat dit inderdaad de juiste weergave is van de bestandsstructuur. Alleen hoe zijn we hier nu aan gekomen?

In plaats van alle tegengekomen resultaten direct in de $output array te plaatsen, controleren we nu eerst of het resultaat een nieuwe directory betreft. Als dat zo is maken we in de $output array een nieuwe key aan met de naam van die map. Vervolgens roepen we de leesUit() functie aan om de waarde voor die key te verzorgen.

Op deze manier is het dus mogelijk om directories tot op oneindige dieptes uit te lezen. Het recursieve gedeelte van de functie zal immers elke keer opnieuw aangeroepen worden. Het grote voordeel van het toepassen van recursie in dit voorbeeld moge duidelijk zijn. Je hoeft namelijk niet van tevoren te weten hoe je bestandstructuur eruit ziet en hoeveel bestanden zich bijvoorbeeld in een bepaalde map bevinden.

Het uitlezen van een directory op een iteratieve manier is natuurlijk mogelijk, maar is vele malen lastiger. Je zult namelijk per directory moeten bepalen hoeveel items die directory bevat, welke items bestanden of mappen zijn en vervolgens van eventuele mappen ditzelfde proces herhalen. Als je een complete directory wilt uitlezen is het dus van tevoren vereist om te weten hoe diep de directory is. En daar heb je in de recursieve functie helemaal geen boodschap aan.

Vorige Volgende