Category tree
Stel, ik heb zo'n tree:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
etc..
(dit zijn dus de id's van de categorien
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
etc..
(dit zijn dus de id's van de categorien
Zo kan het oneindig door gaan.
Stel, ik koppel item 1 aan categorie 3 en 4. Dat zijn dus twee records in de koppel tabel. Ik wil uiteindelijk kan voor item 1 dit weergeven:
Zeg maar net als bij nieuws bij T.net. Kan iemand mij misschien helpen met hoe ik dit kan bereiken? Ik weet dat het lukt met gewoon iedere categorie een parent op geven en dan eerst een query om alles van item 1 uit de koppel tabel te halen en vervolgens eerst alle children selecteren met de id's die in de koppel tabel staan en als parentId niet 0 is nog een query en zo een path opbouwen, maar ik zou dit graaaaag met zo min mogelijk queries doen.
Gr. Thomas.
dus stel je voor
id's | koppel id's
-------------------
1 |
2 | 1
3 | 1
4 | 2
5 |
6 |
En dat je je script zo bouwt dat je dan zo een output krijgt:
1
- 2
-- 4
- 3
5
6
(misschien is er een andere handigere manier ervoor, de enigste manier dat ik op het moment kan bedenken is dit namelijk)
Gewijzigd op 01/01/1970 01:00:00 door Kumkwat Trender
Edit: is het niet het makkelijkste om dit toch met een aantal queries te doen en bij het bewerken op te slaan en direct de output te geven? Maar stel dat ik dan de naam van een categorie bewerk, dan is de output die opgeslagen is niet meer correct. Wat is hiervoor de beste methode?
Gewijzigd op 01/01/1970 01:00:00 door Onbekend Onbekend
Gewoon
stel je voor je gaat alle id nummers na
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
$id=1;
$koppelid2 = "1";
$koppelid6 = "1";
$koppelid7 = "2";
$koppelid8 = "3";
while ($id <= 10) {
if(empty(${'koppelid'.$id})) {
echo $id.'<br>';
} elseif(ctype_digit(${'koppelid'.$id})) {
for($streep=0;$streep<${'koppelid'.$id};$streep++){
echo '<dir>';
}
echo '- '.$id;
for($streep=0;$streep<${'koppelid'.$id};$streep++){
echo '</dir>';
}
}
$id++;
}
?>
$id=1;
$koppelid2 = "1";
$koppelid6 = "1";
$koppelid7 = "2";
$koppelid8 = "3";
while ($id <= 10) {
if(empty(${'koppelid'.$id})) {
echo $id.'<br>';
} elseif(ctype_digit(${'koppelid'.$id})) {
for($streep=0;$streep<${'koppelid'.$id};$streep++){
echo '<dir>';
}
echo '- '.$id;
for($streep=0;$streep<${'koppelid'.$id};$streep++){
echo '</dir>';
}
}
$id++;
}
?>
als output krijg ik
1
---- 2
3
4
5
------ 6
----------- 7
---------------- 8
9
10
Gewijzigd op 01/01/1970 01:00:00 door Kumkwat Trender
Ik snap het wel wat jij nou bedoelt, maar heb je überhaubt mijn post gelezen? Ik wil iets heel anders dan dat jij nu aan het doen bent.
Je hebt drie tabellen:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
-- MENU -- -- ITEMS -- -- MENU_ITEMS --
id id menu_id
name item item_id
childof
left
right
id id menu_id
name item item_id
childof
left
right
Met de volgende waarden:
Code (php)
1
2
3
4
2
3
4
-- MENU -- -- ITEMS -- -- MENU_ITEMS --
1 home 1 nieuwsitem1 2 - 1
2 nieuws 2 nieuwsitem2 2 - 2
3 contact 3 plattegrond 3 - 3
1 home 1 nieuwsitem1 2 - 1
2 nieuws 2 nieuwsitem2 2 - 2
3 contact 3 plattegrond 3 - 3
Wat je uiteindelijke wil is een associatieve array in de trant van:
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
[menu] =>
['home'] => 'home'
['nieuws'] =>
[0] => 'nieuwsitem1'
[1] => 'nieuwsitem2'
['contact'] =>
[0] => 'plattegrond'
['home'] => 'home'
['nieuws'] =>
[0] => 'nieuwsitem1'
[1] => 'nieuwsitem2'
['contact'] =>
[0] => 'plattegrond'
Moet ff weg, als ik zo tijd heb maak ik het wel ff af.
[9:39 uur]
Ik bedacht in één keer dat je ook gewoon alleen menu kan doen en deze iets van een type mee kan geven. (type menuitem, type content)
Er is een 'mooie' PEAR class, deze gebruikt het sorteer principe - ben ik even kwijt -. Komt erop neer: elk item krijgt een nummer links en een nummer rechts. Zo kan alles berekend worden, voorbeeld:
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
1 home 16
2 nieuws 15
3 nieuwsitem1 14
4 nieuwsitem2 13
5 subnieuws 12
6 nieuwsitem3 11
7 contact 10
8 plattegrond 9
[edit]
Sorting heet: Modified Preorder Tree Traversal: http://www.sitepoint.com/article/hierarchical-data-database/2/
[/edit]
2 nieuws 15
3 nieuwsitem1 14
4 nieuwsitem2 13
5 subnieuws 12
6 nieuwsitem3 11
7 contact 10
8 plattegrond 9
[edit]
Sorting heet: Modified Preorder Tree Traversal: http://www.sitepoint.com/article/hierarchical-data-database/2/
[/edit]
Gewijzigd op 01/01/1970 01:00:00 door Jason de Ridder
http://www.phphulp.nl/php/scripts/4/1538/
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$sql = "SELECT id,parent_id,title,link FROM menu";
// ... $results wordt gevuld met de resultaten, via mysqli,pdo whatever
$nested = new Nested ();
foreach($results as $menu_item){
$nested->addChild($menu_item['id'],$menu_item['parent_id'],$menu_item);
}
?>
$sql = "SELECT id,parent_id,title,link FROM menu";
// ... $results wordt gevuld met de resultaten, via mysqli,pdo whatever
$nested = new Nested ();
foreach($results as $menu_item){
$nested->addChild($menu_item['id'],$menu_item['parent_id'],$menu_item);
}
?>
Vervolgens kun je dan makkelijk via een recursieve functie er bijvoorbeeld een html list (<ul>/<li>) van maken voor je menu.
categorien
id INT
parent INT
name TEXT
Als er geen parent is, is het dus een hoofd categorie.
Code (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
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
items
+----------------------------------+
| itemId |
+----------------------------------+
| 1 |
| 2 |
| 3 |
+----------------------------------+
koppelTable
+--------+------------+------------+
| id | itemId | categoryId |
+--------+------------+------------+
| 1 | 1 | 3 |
| 2 | 1 | 4 |
| 3 | 2 | 1 |
| 4 | 3 | 1 |
+----------------------------------+
categories
+--------+------------+------------+
| id | name | parent |
+--------+------------+------------+
| 1 | Test 1 | 0 |
| 2 | Test 2 | 1 |
| 3 | Test 3 | 2 |
| 4 | Test 4 | 1 |
| 5 | Test 5 | 4 |
| 6 | Test 6 | 5 |
+----------------------------------+
+----------------------------------+
| itemId |
+----------------------------------+
| 1 |
| 2 |
| 3 |
+----------------------------------+
koppelTable
+--------+------------+------------+
| id | itemId | categoryId |
+--------+------------+------------+
| 1 | 1 | 3 |
| 2 | 1 | 4 |
| 3 | 2 | 1 |
| 4 | 3 | 1 |
+----------------------------------+
categories
+--------+------------+------------+
| id | name | parent |
+--------+------------+------------+
| 1 | Test 1 | 0 |
| 2 | Test 2 | 1 |
| 3 | Test 3 | 2 |
| 4 | Test 4 | 1 |
| 5 | Test 5 | 4 |
| 6 | Test 6 | 5 |
+----------------------------------+
Dus ik bekijk item 1. Daarbij wil ik dan deze trees weergeven:
Test 1 » Test 2 » Test 3
Test 1 » Test 4
Hoe kan ik dit met zo min mogelijk queries doen? Ik hoop dat het nu een beetje duidelijk id.
Ik gebruik btw MySQL
Edit, is het niet makkelijker om gewoon álle data uit de categorieën tabel te selecteren en uit de koppel tabel en dan een tree bouwen en eventueel server-side cachen?
Gewijzigd op 01/01/1970 01:00:00 door Onbekend Onbekend
Je moet een recursieve functie maken die een loop doorloopt en vervolgens zichzelf aanroept om de childs weer te vinden. Ik had eerst een mooie link waarbij je 2 array's had, een array parents en een array childs.
Code (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
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
array(2) {
[0]=>
array(1) {
[2]=>
array(3) {
["id"]=>
string(1) "2"
["name"]=>
string(6) "Genres"
["children"]=>
array(1) {
[3]=>
array(3) {
["id"]=>
string(1) "3"
["name"]=>
string(8) "Shooters"
["children"]=>
array(1) {
[4]=>
array(3) {
["id"]=>
string(1) "4"
["name"]=>
string(21) "First Person Shooters"
["children"]=>
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "6"
["name"]=>
string(1) "t"
["parent"]=>
string(1) "4"
}
}
}
}
}
}
}
}
[1]=>
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "2"
["name"]=>
string(6) "Genres"
["parent"]=>
string(1) "0"
}
}
}
[0]=>
array(1) {
[2]=>
array(3) {
["id"]=>
string(1) "2"
["name"]=>
string(6) "Genres"
["children"]=>
array(1) {
[3]=>
array(3) {
["id"]=>
string(1) "3"
["name"]=>
string(8) "Shooters"
["children"]=>
array(1) {
[4]=>
array(3) {
["id"]=>
string(1) "4"
["name"]=>
string(21) "First Person Shooters"
["children"]=>
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "6"
["name"]=>
string(1) "t"
["parent"]=>
string(1) "4"
}
}
}
}
}
}
}
}
[1]=>
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "2"
["name"]=>
string(6) "Genres"
["parent"]=>
string(1) "0"
}
}
}
Met deze code:
Code (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
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
<?php
if ($reviewsData[0]['categoriesCacheId'] == "0") {
$categoriesModel = new categoriesModel();
$categoriesDump = $categoriesModel->getAllCategories(0, true, 'parent');
foreach ($categoriesDump as $category) $categoriesData[$category['parentId']] = $category;
unset($categoriesDump);
$categoriesLinks = $reviewsModel->getAllCategoryLinks($reviewsData[0]['reviewId']);
$outputTree = array();
foreach ($categoriesLinks as $link) {
$outputDump = array();
$outputDump[] = array('id' => $categoriesData[$link['category']]['parentId'], 'name' => $categoriesData[$link['category']]['name'], 'parent' => $categoriesData[$link['category']]['parent']);
$stop = true;
$categoryId = $link['category'];
while ($stop) {
$categoryId = $categoriesData[$categoryId]['parent'];
echo $categoryId;
if ($categoryId != 0) {
$outputDumpCopy = $outputDump;
unset($outputDump);
$outputDump = array();
$outputDump[$categoryId]['id'] = $categoryId;
$outputDump[$categoryId]['name'] = $categoriesData[$categoryId]['name'];
$outputDump[$categoryId]['children'] = $outputDumpCopy;
unset($outputDumpCopy);
echo '<hr /><pre>';
var_dump($outputDump);
echo '</pre>';
} else {
$stop = false;
}
}
$outputTree[] = $outputDump;
}
$this->view->assign('v', $outputTree);
}
?>
if ($reviewsData[0]['categoriesCacheId'] == "0") {
$categoriesModel = new categoriesModel();
$categoriesDump = $categoriesModel->getAllCategories(0, true, 'parent');
foreach ($categoriesDump as $category) $categoriesData[$category['parentId']] = $category;
unset($categoriesDump);
$categoriesLinks = $reviewsModel->getAllCategoryLinks($reviewsData[0]['reviewId']);
$outputTree = array();
foreach ($categoriesLinks as $link) {
$outputDump = array();
$outputDump[] = array('id' => $categoriesData[$link['category']]['parentId'], 'name' => $categoriesData[$link['category']]['name'], 'parent' => $categoriesData[$link['category']]['parent']);
$stop = true;
$categoryId = $link['category'];
while ($stop) {
$categoryId = $categoriesData[$categoryId]['parent'];
echo $categoryId;
if ($categoryId != 0) {
$outputDumpCopy = $outputDump;
unset($outputDump);
$outputDump = array();
$outputDump[$categoryId]['id'] = $categoryId;
$outputDump[$categoryId]['name'] = $categoriesData[$categoryId]['name'];
$outputDump[$categoryId]['children'] = $outputDumpCopy;
unset($outputDumpCopy);
echo '<hr /><pre>';
var_dump($outputDump);
echo '</pre>';
} else {
$stop = false;
}
}
$outputTree[] = $outputDump;
}
$this->view->assign('v', $outputTree);
}
?>
Nu is mijn bedoeling om dit te cachen in een tabel en als er iets aan een categorie wordt gewijzigd, de cache items waar de gewijzigde category wordt gebruikt, te verwijderen, en als er geen tree in de cache zit, gewoon een nieuwe maken.