Voor een van mijn sites heb ik het menu geheel in de database staan, zodat dit via een cms gewijzigd kan worden.
In eerste instantie had ik het volgende database schema:
waarbij Id de primary key is.
Dit levert problemen op, wanneer je bijvoorbeeld de volgende DB input (1) hebt:
Wanneer ik dan menuNode 1 wil wijzigen, en ik wil de titel naar 'Thema_1' wijzigen,
dan wordt deze titel niet automatisch geüpdate bij de overige relevante menuNodes.
Omdat ik hier toch vanaf wilde heb ik het DB schema aangepast naar
waarbij Id de primary key is, en ParentId een link naar de parent node (mag NULL zijn)
De inhoud van de database (2) zou er dan nu bijv zo uitzien:
Nu wil ik de data hieruit tonen in een tabel die de vorm heeft als de DB input hiervoor(1) (dus id, thema, rubriek, subrubriek).
Hier komt het eerste probleem al om de hoek kijken: met mySql kan je niet recursief deze data uit de tabel trekken.
Hier komt dus mijn OO idee om de hoek kijken.
Je neemt een Menu object, daar voeg je elke keer een MenuNode object aan toe.
Het Menu object zoekt de goede parent die bij de betreffende MenuNode hoort op, en voegt aan deze parent een nieuw child toe.
Nadat dan alle MenuNodes in het geheugen goed aan elkaar gekoppeld zijn kan je lineair het menu laten tekenen.
Je vraagt aan Menu->geefMenu(), die maakt een String aan, vraagt aan zijn kinderen middels een for-loopje children[$i]->geefMenu() en dat gaat dan recursief door totdat het hele menu weer als String bij het Menu object terug komt.
De volgende code is onderdeel van de twee classes, het probleem zit hem volgens mij in de referentie naar het Parent Object dat ik terug krijg uit de functie zoekParent().
Het lijkt erop dat ik een kopie van het MenuNode object binnen krijg (met telkens weer als ik een child wil toevoegen, dat het weer het eerste kind is, ook al heb ik daarvoor ook al een child toegevoegd aan dit zelfde(?!?) object). Eigenlijk moet ik hier dus een referentie naar de parent MenuNode terug krijgen i.p.v. een kopie ervan.
Menu.php:
Menu.class:
MenuNode.class:
In de methode addNode() in Menu.class echo ik het aantal kinderen van de parent
na het toevoegen aan de parent.
Als ik een tweede node aan de zelfde parent toevoeg, blijft het aantal kinderen
van de parent 1 (of het is opnieuw 1)
Wat zou ik kunnen doen om dit goed te krijgen?
In eerste instantie had ik het volgende database schema:
Id | Thema | Rubriek | SubRubriek |
waarbij Id de primary key is.
Dit levert problemen op, wanneer je bijvoorbeeld de volgende DB input (1) hebt:
1 | Thema1 | ||
2 | Thema1 | Rubriek1 | |
3 | Thema1 | Rubriek2 | |
4 | Thema1 | Rubriek1 | Subrubriek1 |
enz.. |
Wanneer ik dan menuNode 1 wil wijzigen, en ik wil de titel naar 'Thema_1' wijzigen,
dan wordt deze titel niet automatisch geüpdate bij de overige relevante menuNodes.
Omdat ik hier toch vanaf wilde heb ik het DB schema aangepast naar
Id | ParentId | Titel |
waarbij Id de primary key is, en ParentId een link naar de parent node (mag NULL zijn)
De inhoud van de database (2) zou er dan nu bijv zo uitzien:
1 | NULL | Thema1 |
2 | 1 | Rubriek1 |
3 | 1 | Rubriek2 |
4 | 2 | Subrubriek1 |
enz.. |
Nu wil ik de data hieruit tonen in een tabel die de vorm heeft als de DB input hiervoor(1) (dus id, thema, rubriek, subrubriek).
Hier komt het eerste probleem al om de hoek kijken: met mySql kan je niet recursief deze data uit de tabel trekken.
Hier komt dus mijn OO idee om de hoek kijken.
Je neemt een Menu object, daar voeg je elke keer een MenuNode object aan toe.
Het Menu object zoekt de goede parent die bij de betreffende MenuNode hoort op, en voegt aan deze parent een nieuw child toe.
Nadat dan alle MenuNodes in het geheugen goed aan elkaar gekoppeld zijn kan je lineair het menu laten tekenen.
Je vraagt aan Menu->geefMenu(), die maakt een String aan, vraagt aan zijn kinderen middels een for-loopje children[$i]->geefMenu() en dat gaat dan recursief door totdat het hele menu weer als String bij het Menu object terug komt.
De volgende code is onderdeel van de twee classes, het probleem zit hem volgens mij in de referentie naar het Parent Object dat ik terug krijg uit de functie zoekParent().
Het lijkt erop dat ik een kopie van het MenuNode object binnen krijg (met telkens weer als ik een child wil toevoegen, dat het weer het eerste kind is, ook al heb ik daarvoor ook al een child toegevoegd aan dit zelfde(?!?) object). Eigenlijk moet ik hier dus een referentie naar de parent MenuNode terug krijgen i.p.v. een kopie ervan.
Menu.php:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| <?php db_connect(); $query = "SELECT Id, ParentId, Titel FROM menuItems ORDER BY ParentId, Titel"; $result = mysql_query($query); $menu = new Menu; while ($row = mysql_fetch_array($result)) { // variabelen ophalen uit DB $menuNode = new MenuNode($Id, $Parent, $Titel); $menu->addNode($menuNode); } echo $menu->geefMenu(); ?> |
Menu.class:
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
| <?php var $alle_nodes = array(); var $totaalAantalNodes = 0; var $children = array(); var $aantalChildren = 0; function addNode(&$node) { $this->alle_nodes[$this->totaalAantalNodes] = $node; $this->totaalAantalNodes ++; $parentId = $node->geefParentId(); $parent = $this->findParent($parentId); if ($parent != false) { $parent->addChild($node); echo $parent->aantalChildren.'<br>'; } else { $this->addChild($node); } } function findParent($id) { for ($i = 0; $i < $this->totaalAantalNodes; $i ++) { if ($this->alle_nodes[$i]->geefId() == $id) { return $this->alle_nodes[$i]; } } return false; } function addChild(&$node) { $this->children[$this->aantalChildren] = $node; $this->aantalChildren ++; } ?> |
MenuNode.class:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
| <?php var $children = array(); var $aantalChildren; var $titel; var $id; var $parentId; function addChild(&$node) { $this->children[$this->aantalChildren] = $node; $this->aantalChildren ++; } ?> |
In de methode addNode() in Menu.class echo ik het aantal kinderen van de parent
na het toevoegen aan de parent.
Als ik een tweede node aan de zelfde parent toevoeg, blijft het aantal kinderen
van de parent 1 (of het is opnieuw 1)
Wat zou ik kunnen doen om dit goed te krijgen?