[PHP] Onbekend array-item een waarde geven

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Scott
  • Registratie: December 2004
  • Laatst online: 17:26

Scott

Ik ben, dus ik tweak

Topicstarter
Hallo medetweakers,

Ik zit met een probleempje waar ik zelf niet helemaal uitkom. Niet waarom een code niet werkt, maar hoe ik het volgende maak:

Ik wil de mappenstructuur van een vooraf gegeven in een array zetten. Klinkt makkelijk, valt in de praktijk behoorlijk tegen (mij iig). Als voorbeeld een mogelijke mappenstructuur:

code:
1
2
3
4
5
6
- root
    - map 1
        - submap1_1
        - bestand1_1
    - map 2
        - submap 2_1

Dit zou dan tot de volgende array moeten leiden:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
Array
(
    [map 1] => Array
        (
            [submap1_1] => 2
            [bestand1_1] => 3
        )

    [map 2] => Array
        (
            [submap2_1] => 2
        )
)


De values van de array doen er niet zoveel toe, die gebruik ik toch niet.

Nu ben ik al vrij ver, dit is wat ik tot nu toe heb:

PHP:
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
27
28
29
30
31
32
33
34
35
36
function readFiles($dir = false, $depth = 0) {
    
    $dir = ($dir == true) ? $dir : $this->root; // is bij de eerste keer aanroepen het volledige pad
    $dirlist = scandir($dir);
    
    $dirlist = array_flip($dirlist);
    unset($dirlist['..']);
    unset($dirlist['.']);
    
    // Voor het verwijderen van de niet-bestaande mappen . en ..
    
    if ($depth == 0) {
        
        $this->scheme = $dirlist;
        
    }
    
    else {
        $no_root = substr(str_replace($this->root, '', $dir), 1, strlen($dir)); // verwijderen van het volledige pad + de laatste slash op het eind
        
        $dirs = explode('/', $no_root); // alle opeenvolgdende mappen in een array
        
        $array_index = $depth - 1;      
                            
        $this->scheme[$dirs[$depth - 1]] = $dirlist; // de dirlist van een submap toekennen aan een item van de array
                    
    }
    
    foreach ($dirlist as $item => $value) {
        
        if (is_dir($dir.'/'.$item)) {
            
            $this->readFiles($dir.'/'.$item, $depth + 1);
        }
    }
}


Nu gaat het dus fout als ik een map in een map in een map heb zitten. Dan zet hij die als item van de "hoofdarray", en niet als item van een "subarray", wat dus wel mijn bedoeling is.

Nu is mijn voornaamste vraag: hoe kan ik er voor zorgen dat hij een map in een map in een map wel in de juiste subarray zet. Maar, een andere vraag is nog: werk ik niet heel omslachtig en is er niet een heel andere, misschien veel makkelijkere, manier om de mappenstructuur in een array te krijgen ?

Ik hoop dat mijn probleem duidelijk is, maar als er nog vragen zijn dan hoor ik het graag :)

Alvast bedankt! :D

Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 23:28
Volgens mij doe je het redelijk omslachtig ja. Je kunt met recursie immers vrij eenvoudig de arrays dynamisch opbouwen. Zoiets scant al behoorlijk directories:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function tree($dir) {
if (!is_dir($dir)) { return 'Directory doesn't exist'; }
$output = array();

$handle=opendir($dir);
while (false!==($file = readdir($handle))) { 

    if ($file != "." && $file != "..") {
        if (is_dir($dir .$file)) {
            $output[$file] = tree($dir .$file .'/');
        } else {
            $output[$file] = 'file';
        }
    } 
}
closedir($handle);
return $output;
}

[ Voor 11% gewijzigd door T-MOB op 28-04-2006 20:45 . Reden: iets met breaks die dubbel geinterpreteerd werden... ]

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Scott
  • Registratie: December 2004
  • Laatst online: 17:26

Scott

Ik ben, dus ik tweak

Topicstarter
T-MOB schreef op vrijdag 28 april 2006 @ 20:44:
Volgens mij doe je het redelijk omslachtig ja. Je kunt met recursie immers vrij eenvoudig de arrays dynamisch opbouwen. Zoiets scant al behoorlijk directories:
PHP:
1
2
3
function tree($dir) {
..code..
}
Bedankt voor je reactie! Het was dus, wat ik al dacht, een stuk makkelijker te doen. Toch werkt het nog niet, wat ik tijdens het aanpassen ineens zag. De code zoals hij nu is:

PHP:
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
    function readFiles($dir = false) {
    
    $scheme = array();
    
    $dir = ($dir == true) ? $dir : $this->root;
    $dirlist = scandir($dir);
    
    $dirlist = array_flip($dirlist);
    unset($dirlist['..'], $dirlist['.']);
            
    foreach ($dirlist as $item => $value) {
        
        if (is_dir($dir.'/'.$item)) {
            
            $scheme[$item] = $this->readFiles($dir.'/'.$item);
        }
        
        else {
            
            $scheme[$item] = 'file';
        }
    }
    
    return $scheme;
}


Zoals je ziet heb ik je code niet letterlijk overgenomen, maar het idee is hetzelfde. Hij schrijft nu altijd, zonder te kijken naar of het een submap is, het item in de root van de array zet. Het is dus de bedoeling dat het dan een multidimensionale array wordt. Heb je hier misschien ook een oplossing voor ? :)

[ Voor 18% gewijzigd door Scott op 30-04-2006 21:46 ]


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 23:28
ScottB schreef op zondag 30 april 2006 @ 21:42:
[...]


Bedankt voor je reactie! Het was dus, wat ik al dacht, een stuk makkelijker te doen. Toch werkt het nog niet, wat ik tijdens het aanpassen ineens zag. De code zoals hij nu is:

PHP:
1
...

Het is dus de bedoeling dat het dan een multidimensionale array wordt. Heb je hier misschien ook een oplossing voor ? :)
De code uit mijn vorige post geeft je een multidimensionaal array terug (en voor zover ik kan inschatten - heb een PHP-versie zonder scandir - doet jouw functie hetzelfde). Ik zal een poging doen om de recursie uit te leggen...

De functie geeft _altijd_ een array terug, in jouw geval is dat $scheme. Omdat een functie zijn eigen scope heeft zal bij elke aanroep een nieuw array gemaakt worden.
De waarden van de output array halen we uit de directory listing. Wanneer we de functie aanroepen met '/var/www' loopen we dus door alle files en mappen die in deze map staan. Vervolgens kijken we voor al die entries of het om een map gaat of om een bestand. Als het om een bestand gaat voegen we 'file' toe aan ons array. Gaat het om een bestand dan roepen we recursief de functie opnieuw aan. Hierin wordt een nieuw "scheme"-array aangemaakt met de bestanden en mappen uit de subdir, het resultaat wijzen we toe aan de scheme-array van de eerste functiecall.
Zou in de tweede functiecall ook een subdir gevonden worden dan wordt middels een derde functiecall een derde "scheme"-array worden aangemaakt. Deze zou worden toegevoegd aan het scheme-array uit de tweede functie, waarna dit array uit de tweede functie wordt toegevoegd aan het array uit de originele functieaanroep. De recursie zorgt er dus voor dat de uitvoer van de eerste functiecall altijd even diep is als het bestandssysteem.
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
27
28
29
//scan de dirs
$var = readFiles('/var/www/');

// dit is wat er gebeurt 
readfiles('/var/www/')
 -> array(
   [index.html]     => file
   [includes]       => readFiles('/var/www/includes/')
                        -> array(
                        [inc.db.php]    => file
                        [subdir]        => readFiles('/var/www/includes/subdir/')
                                            -> array(
                                                [foo]   => file
                                                [bar]   => file

//dit is dus $var:
Array
(
    [index.html] => file
    [includes]   => Array
        (
            [inc.db.php] => file
            [subdir]     => Array
                (
                    [foo] => file
                    [bar] => file
                )
        )
)

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Scott
  • Registratie: December 2004
  • Laatst online: 17:26

Scott

Ik ben, dus ik tweak

Topicstarter
Allereerst: het werkt :D

Ik wist wel al hoe recursies werken, desalniettemin bedankt voor je uitleg, uiteindelijk heeft dit geleid tot het oplossen van mn probleem. Wat ik deed, was de variabele $this->scheme in elke recursie overschrijven. Dat besefte ik bij het lezen van jouw tekst ineens ('De functie geeft _altijd_ een array terug'). Bij mij deed hij dat niet, maar hij schreef dat naar een variabele in de class. Die werd dus steeds overschreven.

Nu werkt het wel, heel erg bedankt voor de hulp, weer wat er bij geleerd :*)