Avatar billede intel4004 Novice
24. august 2003 - 18:43 Der er 16 kommentarer og
1 løsning

Problem med multidimensionelt-array

Jeg har efterhånden rodet godt og grundigt rundt i tingene. Jeg har en hjemmelavet funktion som returnerer et array bestående af samme struktur som katalog strukturen i et bibliotek. Er i med?
Dette betyder at arrayet er rimelig dynamisk med hvad angår den egentlig dimension. Mit test-bibliotek danner eksempelvis et array på 10-dimensioner maks.

Mit problem er egentlig i retning af variable variabler.

Jeg generer en almindelig tekst-streng med følgende indhold:

$_str = [0]['DIRECTORIES'][4]['DIRECTORIES'][1]['FILES'];

Det er så meningen at jeg vil benytte $_str til at identificere hvor jeg vil hen i mit super-array!

eksempelvis:

$super_array[0]['DIRECTORIES'][4]['DIRECTORIES'][1]['FILES'];

Men det fungerer ikke. Hvordan kan jeg klistre $_str på variabelnavnet $super_array så det fungerer.

Har prøvet $super_array{$_str}; Men nej. Hvad med eval(), kan man bruge den?

Mvh Intel4004
Avatar billede erikjacobsen Ekspert
24. august 2003 - 18:46 #1
jah du kan jo altid

  $t = "\$super_array$_str";

  $x = eval("$t[7}");

men, hvad om vi tænkte dit problem igennem for måske at finde en anden løsning
Avatar billede erikjacobsen Ekspert
24. august 2003 - 18:46 #2
dvs.
  $x = eval("$t[7]");
Avatar billede limemedia Nybegynder
24. august 2003 - 18:55 #3
må man få et kig på din funktion, måske en alternativ løsning kan findes - lyder som om du har trukket de store kanoner frem for at ramme den forholdsvist hamløse due
Avatar billede intel4004 Novice
24. august 2003 - 19:07 #4
Ok - den kan sikkert laves anderledes. Men det den returnerer er ligesom jeg vil have det:

function walk_dir($_dir = '.' , $_is_root = TRUE)
{
    $__FUNCTION__ = __FUNCTION__;  // __FUNCTION__ from php 4.3.0
    $dirhandle = opendir($_dir);
    while (($item = readdir($dirhandle)) !== FALSE)
    {
          if ($item != "." && $item != ".." && !is_dir($_dir.'/'.$item))
        {
            if (substr($_dir, 0, 2) == './')
            {
                $_printdir = substr($_dir, 2);
            }
            if (!$_is_root)
            {
                $sub_dirdata['FILES'][] = $_printdir.'/'.$item;
            }
            else
            {
                $files_in_root[] = $item;
            }
      }
        if ($item != "." && $item != ".." && is_dir($_dir.'/'.$item))
        {
            $newdir = $_dir.'/'.$item;
            if ($_is_root)
            {   
                $dirdata[] = $__FUNCTION__($newdir, FALSE); // __FUNCTION__ from php 4.3.0
            }
            else
            {
                $sub_dirdata['DIRECTORIES'][] = $__FUNCTION__($newdir, FALSE);
            }
        }
    }
    closedir($dirhandle);
    if (!$_is_root)
    {
        if (!isset($sub_dirdata))
        {
            return array(
                array_merge(array(
                    'FILES' => array()),
                    array('DIRECTORIES' => array())
                )
            );
        }
        else
        {
            if (!isset($sub_dirdata['FILES']))
            {
                $sub_dirdata['FILES'] = array();
            }
            if (!isset($sub_dirdata['DIRECTORIES']))
            {
                $sub_dirdata['DIRECTORIES'] = array();
            }
        }
        return $sub_dirdata;
    }
    else
    {
        return array(
            array_merge(array(
                'FILES' => $files_in_root),
                array('DIRECTORIES' => @$dirdata)
            )
        );
    }
}
Avatar billede limemedia Nybegynder
24. august 2003 - 19:59 #5
Jeg tillod mig at lege med din kode...

<?php
    function walk_dir($res=array(), $dir='.', $level=0) {
        $thisdir = array();
        $thisdir['level'] = $level;       
        $thisdir['dir'] = $dir;       
        $thisdir['files'] = array();
        $thisdir['folder'] = array();

        $od = opendir($dir);
        while (($item = readdir($od)) !== FALSE) {
            if ($item != "." && $item != "..") {
                if (!is_dir($dir.'/'.$item)) $thisdir['files'][] = $item;
                else $thisdir['folder'][] = $item;
            }
        }
       
        $res[] = $thisdir;


        for ($i=0; $i<sizeof($thisdir['folder']); $i++) {
            $res = walk_dir($res, $dir.'/'.$thisdir['folder'][$i], $level+1);
        }

        return $res;
    }

    $fl = walk_dir();

    echo "<pre>";
    print_r($fl);
    echo "</pre>";
?>

Hele dit directory tree vil være i ét array, for hver post er et directory. Denne post vil være et array, med følgende
  [level] = hvor dybt er vi
  [dir] = stien til folderen
  [folder] = indeholder et array af biblioker i denne folder
  [files] = indeholder et array af filer i denne folder

Du vil kunne sammenligne [level] værdier for at danne dit træ

/ LJ
Avatar billede intel4004 Novice
24. august 2003 - 20:15 #6
ljweb>

Din funktion er super(noget mere kompakt end mit), men mit problem er sådan set ikke det array som det returnerer. Tror jeg ikke.

Problemet ligger i at jeg sender et argument som eksempelvis:

index.php?c=0,5,4.3

Dette betyder at scriptet skal kigge i de forskellige keys i dimensionerne. Altså [0]['DIRECTORIES'][5]['DIRECTORIES'][4]['FILES'][3]. Komma adskiller biblioteker, og efter punktum kommer nummeret på filen. Her har jeg brug for, dynamisk at generere den lange tekst-streng, og herefter klistre den på variabel-navnet.

Tekststrengen er nem nok at fremstille udfra argumentet, men jeg har stadig ikke fundet en løsning til det oprindelige problem.

Intel4004
Avatar billede limemedia Nybegynder
24. august 2003 - 20:33 #7
uden du forklarer hvorfra du får index.php?c=0,5,4.3 (sikkert fra en dirliste hvor du vil udprinte filer) vil den i mit eksempel hedde fx index.php?c=21 hvor du så bruger $fl[$_GET['c']]['dir'] til fx at udskrive dir navnet ?
Avatar billede intel4004 Novice
24. august 2003 - 21:03 #8
ok - fik ikke testet din funktion ordentlig. Det er jo meget smartere. Så er har man kun brug for at bruge 1 dimension (og tallet som definerer dybden).

Takker.

Du har tjent de 80 point da jeg tror det virker bedre nu. Men har du en løsning på det oprindelige spørgsmål??

Intel4004
Avatar billede erikjacobsen Ekspert
24. august 2003 - 22:46 #9
Disse indices: 0,5,4,3 eller bare 21, hvor længe eksisterer de? Der er ingen
garanti for at filsystemet afleverer filerne i samme rækkefølge hver gang.
Filer kan slettes og tilføjes, og der kan ske andre ting. Det forekommer mig
at være en usund måde at gøre det på.

Hvad er det egentlig du prøver at lave?
Avatar billede intel4004 Novice
24. august 2003 - 23:32 #10
Det jeg prøver at lave er noget jeg har villet prøve længe. Jeg har fundet at det er styrkende at rode med arrays til diverse formål.

Det skal bruges til en form for fil-browser. Jeg vil bare gerne have stien væk fra adresse-linien som et argument. Derfor var min første tanke at jeg kunne parse nogle koordinater til et array om hvilken fil jeg ville have, hvor henne i hvilken dybde osv.

Hvordan usund? Jeg er ikke helt ny i PHP :).

PS: Lad nu vær med at diske op med en funktion i lavede til et stykke franskbrød for 3 år siden, som bare kan det hele. Jeg morer mig ved selv at lave det :).

Intel4004
Avatar billede erikjacobsen Ekspert
24. august 2003 - 23:40 #11
Hvis din filstruktur er 100% statisk går det vel. Men hvis en fil har nummer 5, og
der imellemtiden bliver fjernet eller tilføjet en fil, har den sikkert ikke nummer
5 længere. Det mener jeg med "usund" - franskbrød er ikke usundt *g*
Avatar billede limemedia Nybegynder
25. august 2003 - 03:04 #12
erik >> jeg vil formode en sådan funktion skal køre rent internt i et admin system af en slags - hvorfor det vil være admins med kontrol over maskinen som anvender funktionen - det er ganske korrekt at slettes indhold mellem listen genereres og evt. links klikkes, vil resultatet kunne fejle med noget "dir not found" osv.

intel >> fil browser med at fjerne stien, lyder som en langsom funktion - at du for hver sideskift skal liste alle dirs, filer osv for at udtrække et par enkelte filer. Måske mod_rewrite på Apache kan give dig en pænere sti i adresselinien, uden at det kræver så meget fil gymnastik
Avatar billede intel4004 Novice
25. august 2003 - 08:40 #13
Jeg tror da også det er lidt langsomt. Det er dog tit at udfordringen med at udvikle det dominerer. Jeg bruger desværre IIS på XP.

Når jeg lister filer og biblioteker i roden, får alle links disse indices.

Men det er altså også kun til hobby, og ikke noget alvorligt produktions-script.

Intel4004
Avatar billede erikjacobsen Ekspert
25. august 2003 - 09:59 #14
Ok med hobby. Så er der bare det tilbage at rækkefølgen for en readdir
ikke er deterministisk - det garanteres i hvert fald ikke. Kører serveren
en fil-oprydning (manuelt, automatisk, ...) kan du risikere at få forskellige
resultater. Du vil sandsynligvis kunne afteste det 100vis af gange, hvor
det virker, og så en dag, på et andet/nyt filsystem/OS, så virker det ikke.
Nå ja, det var bare hobby.
Avatar billede limemedia Nybegynder
25. august 2003 - 10:03 #15
erik >> udskift
$res[] = $thisdir;
med
$res[urlencode($thisdir['dir'])] = $thisdir;

og problemet du antyder vil være minimalt... eller hvilken vinkel ser du problemet fra ;)
Avatar billede intel4004 Novice
25. august 2003 - 14:19 #16
Jeg hsr fået det til at fungere nogenlunde. Vha. ljweb's funktion er det blevet realistisk at jeg får det til at fungere.

Men problemet ligger i naturen i et katalogstruktur. Ideen er at jeg lister alle filer og mapper i roden - dette vil sige at scriptet har fået indices ?=0,0,0 (level, nummer på mappen, og nummer på fil). Filen er den egentlige destination som bliver vist forneden. Den første fil i mappen bliver vist automatisk. Klikker jeg et mappenavn loades scriptet igen med ?=1,0,0 hvor mappe nummer 0 vises i level 1 - er i med.

På denne måde med designerer jeg en form for koordinat. Men på vej tilbage er der et problem. Hvordan kan i et sub-sub-sub-sub-dir identificere det forrige dirs nummer i den træ-dybde (level), og det forrige ... og det forrige ... osv. Man bliver nødt til at medbringe en history for ens browsing tilbage op i strukturen. En ekstra oplysning er altså nødvendig:

?=2,4,{4,4},3 : level 2, dir nr. 4, {historien til backtrack i strukturen), og fil nummeret.

Det fungerer - men det er langsomt. Jeg kan for sjov skyld poste et link til scriptet, når jeg synes det er færdigt (hvis det har interesse).

PS: Scriptet går udfra at filernes rækkefølge forbliver det samme gennem browsing af katalogstrukturen.

Intel4004
Avatar billede intel4004 Novice
26. august 2003 - 17:54 #17
Nå - scriptet fungerer lokalt med IIS - men på 1go.dk kontoen kan jeg ikke få listet nogle filer overhovedet. Noget med rettigheder på filsystemet?

Intel4004

Pointene går til ljweb
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester