Php; alle childs zoeken
Voor de puzzelaars onder ons een leuke kwestie...
Ik ben bezig met een folder-systeem.
Mijn tabel (kort):
id | parent_id
m2 | NULL
m21 | m2
m22 | m2
m23 | m2
m26 | m22
m29 | m26
m30 | m26
Een folder heeft dus een id, en een parent_id (dat is de id van de map die boven hem ligt.
Stel, ik wil een map verwijderen moet ik ook al zijn childs verwijderen.
Daarvoor wil ik een array hebben met alle childs.
Hiervoor zijn denk ik 2 functies nodig.
1) getchild($var). Deze functie (heb ik al), geeft een array met alle childs van de map $var.
2) allchilds($var). Deze functie (???), zal in de array moeten zoeken en de getchild() uit moeten voeren en zijn array uitbreiden...
Hoe moet ik dit bouwen? Hoe laat ik hem zichzelf herhalen totdat er geen childs meer zijn en hoe zet ik dat in een nette array?
ps. Ik werk in CakePhp, maar tips zijn op welke manier dan ook welkom!
Alvast bedankt!
Dus, de oplossing, gebruik een nested set model: http://en.wikipedia.org/wiki/Nested_set_model
Wat lastiger om te bouwen, maar dat werkt in elk geval wel. En voor jouw probleem heb je dan een vrij simpele oplossing:
Wanneer je je database iets beter in elkaar gezet had kon je de Iterator pattern gebruiken om langs alle childs te gaan van een bepaalde map en deze wissen.
Folder systeem, dan denk ik meteen aan PHPCR!
Erwin H op 07/10/2013 20:06:39:
Dus, de oplossing, gebruik een nested set model: http://en.wikipedia.org/wiki/Nested_set_model
Wat lastiger om te bouwen, maar dat werkt in elk geval wel. En voor jouw probleem heb je dan een vrij simpele oplossing
Dus, de oplossing, gebruik een nested set model: http://en.wikipedia.org/wiki/Nested_set_model
Wat lastiger om te bouwen, maar dat werkt in elk geval wel. En voor jouw probleem heb je dan een vrij simpele oplossing
Erwin, bedankt voor je verhelderende woord. Ziet er wel lastig uit; hoe bouw je dit terwijl alles variabel is?
Hier kan ik mee verder!
Als je een tabel hebt met een id (auto increment), lft, rgt en name veld, dan zou de root bijvoorbeeld 1 (lft), 2 (rgt), 'root' (name) zijn. Wil je dan een node toevoegen dan moet dat dus een child van de root worden en na het toevoegen van de node moeten de lft en rgt waardes als volgt zijn:
Wil je dan een node toevoegen als kind van node1, dan krijg je dit:
Hieruit kan je al het patroon opmerken van hoe je de lft en rgt waardes moet aanpassen bij een insert van een nieuwe node. De nieuwe node krijgt als lft waarde de rgt waarde van zijn nieuwe parent, als rgt waarde wordt lft+1 en alle lft en rgt waardes in de boom die groter of gelijk zijn aan de rgt waarde van de nieuwe parent moeten met twee opgehoogd worden. Als sql queries heb je dus dit nodig:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
//zorg dat je de rgt waarde van de nieuwe parent weet, die moet overal op de stippellijnen worden ingevuld
UPDATE tree
SET lft = lft+2
WHERE lft > ....
ORDER BY lft DESC;
UPDATE tree
SET rgt = rgt+2
WHERE rgt >= ....
ORDER BY lft DESC;
INSERT INTO tree(lft, rgt, name)
VALUES(..., ...+1, 'nodeX');
UPDATE tree
SET lft = lft+2
WHERE lft > ....
ORDER BY lft DESC;
UPDATE tree
SET rgt = rgt+2
WHERE rgt >= ....
ORDER BY lft DESC;
INSERT INTO tree(lft, rgt, name)
VALUES(..., ...+1, 'nodeX');
De ordering in de update queries is alleen nodig als je een unieke index gebruikt op de lft en rgt kolommen.
Bij voorkeur verpak ik al deze queries in een stored procedure om het bij elkaar te houden en zodat je zeker weet dat je niet een update vergeet.
Bedankt voor je mooie uitleg.
Heel duidelijk!
Ik ben er nu mee bezig en je voorbeeld werkt uitstekend!
Bedankt!!!
Gewijzigd op 08/10/2013 19:40:16 door Simon Simons
Als het inserten lukt, dan is de volgende taak om elementen uit de boom te halen. Ook daar zal je de boom moeten herstructureren op een soortgelijke manier.
Hoe verwijder je nu submappen? Reken je dan ook terug met lft en rgt of laat je dat voor wat het dan is?
Toevoeging op 08/10/2013 21:50:38:
Genoeg te leren...
http://falsinsoft.blogspot.nl/2013/01/tree-in-sql-database-nested-set-model.html
Erwin H op 08/10/2013 20:10:56:
Als het inserten lukt, dan is de volgende taak om elementen uit de boom te halen. Ook daar zal je de boom moeten herstructureren op een soortgelijke manier.
Als je niets doet aan de lft en rgt waardes dan gaat je hele boomstructuur naar de knoppen.
Kan ik mijn tabel ook meerdere 'roots' hebben met dezelfde lft en rgt? (1 en 2?)
Nee, want als je dan van een child van de een alle roots wil hebben, krijg je ook de andere root (en subroots). Wat je wel kan doen is een 'dummy' root maken, die weer de root is van je beide roots. Zo kan je twee bomen bouwen binnen dezelfde tabel, waarbij dus beide bomen een sub zijn van de dummy root.