[PHP / MySQL] Navigatie boomstructuur in multidimens.-array

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Speed_Sheep
  • Registratie: Augustus 2001
  • Laatst online: 25-11-2021
Ik ben bezig met het maken van een navigatiesysteem. Alle boomstructuur voorbeelden geven allemaal in hun functie al HTML terug, door gewoon echo's te gebruiken. Dat lukt mij ook prima, maar dat wil ik echter niet. Ik wil de navigatie structuur namelijk in een multidimensionale array teruggeven.
Op basis van een voorbeeld om een directorystructuur in een multidimensionale array te proppen, heb ik mijn code geschreven. (http://www.php.net/dir , post door fabrizio)

Ik sla gegevens op de volgende manier in de database op:
code:
1
2
3
4
5
6
7
8
9
10
11
nnavid   nparentid      snavtitle
1       0           Home
2       0           Arbeidsintegratie
3       0           Industrie
4       0           Groen en Dienstverlening
5       1           Personeelszaken
6       1           Concerninfo
7       1           Financien
8       5           ABC van de arbeidsvoorwaarden
9       5           Formulieren
10      5           PZ Info


De navigatiestructuur haal ik op met onderstaande code en haal ik op door getNavigationStructure() aan te roepen.
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
function getNavigationStructure()
{
    return $this->getNavigationChildren(0);
}

function getNavigationChildren($nparentId)
{
    if (!is_numeric($nparentId))
    {
        return false;
    }
    else
    {
        // retrieve all children of $nparentId
        $qry =  'SELECT nnavid, nparentid, snavtitle ' .
                    'FROM navigation ' .
                    'WHERE nparentid = ' . $nparentId;
        
        $result = mysql_query($qry);
        while ($row = mysql_fetch_array($result))
        {
            $a_navigation[] = $row;
            $a_navigation[$row['nnavid']] = $this->getNavigationChildren($row['nnavid']);
        }
        return $a_navigation;
    }
}


var_dump(getNavigationStructure()); resulteert in het volgende:
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
array(5) {
  [0]=>
  array(6) {
    [0]=>
    string(1) "1"
    ["nnavid"]=>
    string(1) "1"
    [1]=>
    string(1) "0"
    ["nparentid"]=>
    string(1) "0"
    [2]=>
    string(4) "Home"
    ["snavtitle"]=>
    string(4) "Home"
  }
  [1]=>
  array(4) {
    [0]=>
    array(6) {
      [0]=>
      string(1) "5"
      ["nnavid"]=>
      string(1) "5"
      [1]=>
      string(1) "1"
      ["nparentid"]=>
      string(1) "1"
      [2]=>
      string(15) "Personeelszaken"
      ["snavtitle"]=>
      string(15) "Personeelszaken"
    }
    [5]=>
    array(4) {
      [0]=>
      array(6) {
        [0]=>
        string(1) "8"
        ["nnavid"]=>
        string(1) "8"
        [1]=>
        string(1) "5"
        ["nparentid"]=>
        string(1) "5"
        [2]=>
        string(29) "ABC van de arbeidsvoorwaarden"
        ["snavtitle"]=>
        string(29) "ABC van de arbeidsvoorwaarden"
      }
      [8]=>
      NULL
      [9]=>
      NULL
      [10]=>
      NULL
    }
    [6]=>
    NULL
    [7]=>
    NULL
  }
  [2]=>
  NULL
  [3]=>
  NULL
  [4]=>
  NULL
}


Zoals je dus ziet haalt hij de navigatiestructuur maar in 1 "lijn" goed op. De andere array elementen kloppen wel op de goede positie, maar hebben ze echter allemaal waarde NULL... |:(
Iemand idee wat fout zit?

[ Voor 10% gewijzigd door Speed_Sheep op 02-08-2004 16:54 ]

Systeemspecs


Acties:
  • 0 Henk 'm!

Verwijderd

PHP:
1
  $a_navigation[$row['nnavid']] = $this->getNavigationChildren($row['nnavid'], 0);

Waar is die tweede parameter voor?

Als ik het goed begrijp voer je nu voor elke aftakking binnen je menu een nieuwe query op om de children/onderliggende nodes op te halen. Met een paar aftakkingen gaat dat wel, maar als je veel aftakkingen hebt is het beter om een andere oplossing te kiezen. Ergens op het forum is al eens een oplossing gegeven met 1 query, waarna met PHP verder de structuur in de array is aangebracht.

Acties:
  • 0 Henk 'm!

Verwijderd

Hier:

PHP:
1
2
3
4
5
6
7
        $result = mysql_query($qry); 
        while ($row = mysql_fetch_array($result)) 
        { 
            $a_navigation[] = $row; 
            $a_navigation[$row['nnavid']] = $this->getNavigationChildren($row['nnavid'], 0); 
        } 
        return $a_navigation;


Ten eerste initialiseer je de array niet. Dat is niet persé nodig, maar wel veel netter (en in willekeurig welke andere taal moet je het ook doen, dus kun je het je maar beter aanleren ;)).

Verder is het met deze code niet gegarandeerd dat de twee assignments in hetzelfde record terecht komen. Ik snap ook niet precies wat je probeert te bereiken. Maar wat je nu doet is:

1. Voeg een database-rij toe aan de array. Deze worden automatisch oplopend genummerd, maar als je deze notatie gebruikt moet je daar niet vanuit gaan in je code. Dat is namelijk tamelijk obscuur gebruik, en behoorlijk fout gevoelig. Als je indexen wilt gebruiken, maak die dan expliciet, en als je dat niet doet, moet je geen indexen gebruiken. B)
2. Daarna ga je op de index van het record in het array de verzameling van de kinderen zetten. Dit kan dezelfde index zijn als de vorige rij (hoeft niet, dus, als je een niveau dieper zit of je items komen niet oplopend genummerd uit de database terug, dan is dit niet!). Zo ja, dan overschrijf je de vorige gegevens, zo nee, dan ben je op zijn best twee verschillende soorten gegevens in één container aan het stoppen, en op zijn slechts kun je de gegevens niet eens meer aan elkaar passen. Nou kan het hier nog wel, maar echt netjes is het niet.

Waarom doe je het niet zo:
PHP:
1
2
3
4
5
6
7
8
       $result = mysql_query($qry); 
       $a_navigation = Array();
        while ($row = mysql_fetch_array($result)) 
        { 
            $row["children"] = $this->getNavigationChildren($row["nnavid"]);
            $a_navigation[] = $row; 
        } 
        return $a_navigation;


En zoals RobinVR al heeft opgemerkt, beknibbelen op queries is altijd een goed idee, dus je zou kunnen overwegen de gegevens in 1 query op te halen en de boom daarna puur in PHP te bouwen.

[ Voor 19% gewijzigd door Verwijderd op 02-08-2004 17:04 ]


Acties:
  • 0 Henk 'm!

  • Speed_Sheep
  • Registratie: Augustus 2001
  • Laatst online: 25-11-2021
2e parameter was nog om level dieptes bij te houden, maar dat was nog oud en ging boel niet van op z'n snufferd. (inmiddels aangepast)

De posts om het geheel in 1 keer op te halen heb ik meerdere malen voorbij zien komen. Nu opnieuw wezen zoeken, maar vind het echter niet dat ze deze ook in een array stoppen. Ik zoek nog verder, maar heb al flinke tijd gezocht, ook gegoogeld, maar helaas nog geen resultaat. Als je de post zou kunnen aanwijzen, dan zou dat mooi zijn.

Het meerdere keren aanroepen van query ben ik me bewust van. Dit is echter hier geen probleem, moet namelijk alleen aan beheerskant gedaan worden, waarbij servertijd niet echt belangrijk is en veel menuitems komt niet vaak voor.
Dus opzich wil ik ook wel aan mijn huidige concept verder werken. Beide oplossingen zijn prima.

Systeemspecs


Acties:
  • 0 Henk 'm!

  • bras
  • Registratie: Oktober 2000
  • Laatst online: 27-06 15:56
Als ik me niet vergis overschrijf je bij elke query je oude resultset. Een oplossing zou zijn om telkens je hele result set uit te lezen en dan daar recursief in te gaan.

"When you find yourself in the company of a halfling and an ill-tempered Dragon, remember, you do not have to outrun the Dragon...you just have to outrun the halfling."


Acties:
  • 0 Henk 'm!

  • Speed_Sheep
  • Registratie: Augustus 2001
  • Laatst online: 25-11-2021
Bedankt RobinVR en OneOfBorg. M'n getNavigationChildren functie aangepast naar het volgende en het werkt nu. _/-\o_
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function getNavigationChildren($nparentId)
{
    if (!is_numeric($nparentId))
    {
        return false;
    }
    else
    {
        // retrieve all children of $nparentId
        $qry =  'SELECT nnavid, nparentid, snavtitle ' .
                'FROM navigation ' .
                'AND nparentid = ' . $nparentId;
        
        $result = mysql_query($qry);
        $a_navigation = Array();
        while ($row = mysql_fetch_array($result))
        {
            $row["children"] = $this->getNavigationChildren($row["nnavid"]);
            $a_navigation[] = $row;
        }
        return $a_navigation;
    }
}

Later als ik tijd heb, dan ga ik het in 1 query oplossen. Helaas op werk is: Tijd=geld, dus hou ik het bij deze oplossing. ;)

Systeemspecs

Pagina: 1