Categoriemenu opbouwen
In mijn website maak ik gebruik van categorieën.
Elke categorie kan een andere categorie als parent hebben(de gebruiker bepaalt zelf hoe diep hij gaat)
nu wil ik een menu opbouwen uit deze categorieeën
bv
Categorie 1 (catID = 1)
Categorie 2 (catID = 2)
- Subcategorie 1 (catID = 3)
- Subcategorie 2(catID = 4)
-- SubSubCategorie1(catID = 5)
-- SubSubCategorie2(catID = 6)
Categorie 3(catID = 7)
Kan iemand me op weg zetten?
Alvast bedankt
Stille hint: Kun je beter niet doen. Google op "database normaliseren", ik geloof dat er hier een tut op php-hulp staat.
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
57
58
59
60
61
62
63
64
65
66
67
68
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
<?php
// Even een testdatabase bakken
$pdo = get_me_my_test_db();
// Let op de volgorde waarin je ze ophaalt. De parents van de children moeten
// als eerste worden opgehaald, anders gaat m'n foreach lus straks krom wanneer
// ik een child probeer toe te voegen aan een parent die ik nog niet heb
// opgehaald.
$stmt = $pdo->query("SELECT id, parent_id, name FROM menu ORDER BY parent_id ASC, id ASC");
$menu_items = array(); // tijdelijke array om parents en children te verenigen
$menu = array(); // uiteindelijke menu, met alle menuitems zonder parent.
// Ik gebruik hier objecten omdat die standaard soort van 'by reference' worden
// opgeslagen. Als ik het met arrays zou doen zou ik heel erg moeten opletten op
// m'n references.
foreach ($stmt->fetchAll(PDO::FETCH_OBJ) as $menu_item)
{
$menu_items[$menu_item->id] = $menu_item;
if ($menu_item->parent_id)
$menu_items[$menu_item->parent_id]->children[] = $menu_item;
else
$menu[] = $menu_item;
}
// Recursieve functie die een menu print. Met de juiste indent nog wel.
function print_menu(array $menu, $indent = "")
{
echo $indent . "<ul>\n";
foreach ($menu as $menu_item)
{
echo $indent . "\t<li>" . $menu_item->name . "</li>\n";
if (isset($menu_item->children))
print_menu($menu_item->children, $indent . "\t");
}
echo $indent . "</ul>\n";
}
print_menu($menu);
function get_me_my_test_db()
{
$pdo = new PDO('sqlite:/tmp/menu.db');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->query("DROP TABLE IF EXISTS menu");
$pdo->query("CREATE TABLE menu (
id INTEGER PRIMARY KEY,
parent_id INTEGER DEFAULT NULL,
name VARCHAR(255)
)");
// En wat troep erin stoppen
$stmt = $pdo->prepare("INSERT INTO menu (id, parent_id, name) VALUES (?, ?, ?)");
$stmt->execute(array(1, NULL, 'Categorie 1'));
$stmt->execute(array(2, NULL, 'Categorie 2'));
$stmt->execute(array(3, 2, 'Subcategorie 1'));
$stmt->execute(array(4, 2, 'Subcategorie 2'));
$stmt->execute(array(5, 4, 'SubSubCategorie 1'));
$stmt->execute(array(6, 4, 'SubSubCategorie 2'));
$stmt->execute(array(7, NULL, 'Categorie 3'));
return $pdo;
}
?>
// Even een testdatabase bakken
$pdo = get_me_my_test_db();
// Let op de volgorde waarin je ze ophaalt. De parents van de children moeten
// als eerste worden opgehaald, anders gaat m'n foreach lus straks krom wanneer
// ik een child probeer toe te voegen aan een parent die ik nog niet heb
// opgehaald.
$stmt = $pdo->query("SELECT id, parent_id, name FROM menu ORDER BY parent_id ASC, id ASC");
$menu_items = array(); // tijdelijke array om parents en children te verenigen
$menu = array(); // uiteindelijke menu, met alle menuitems zonder parent.
// Ik gebruik hier objecten omdat die standaard soort van 'by reference' worden
// opgeslagen. Als ik het met arrays zou doen zou ik heel erg moeten opletten op
// m'n references.
foreach ($stmt->fetchAll(PDO::FETCH_OBJ) as $menu_item)
{
$menu_items[$menu_item->id] = $menu_item;
if ($menu_item->parent_id)
$menu_items[$menu_item->parent_id]->children[] = $menu_item;
else
$menu[] = $menu_item;
}
// Recursieve functie die een menu print. Met de juiste indent nog wel.
function print_menu(array $menu, $indent = "")
{
echo $indent . "<ul>\n";
foreach ($menu as $menu_item)
{
echo $indent . "\t<li>" . $menu_item->name . "</li>\n";
if (isset($menu_item->children))
print_menu($menu_item->children, $indent . "\t");
}
echo $indent . "</ul>\n";
}
print_menu($menu);
function get_me_my_test_db()
{
$pdo = new PDO('sqlite:/tmp/menu.db');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->query("DROP TABLE IF EXISTS menu");
$pdo->query("CREATE TABLE menu (
id INTEGER PRIMARY KEY,
parent_id INTEGER DEFAULT NULL,
name VARCHAR(255)
)");
// En wat troep erin stoppen
$stmt = $pdo->prepare("INSERT INTO menu (id, parent_id, name) VALUES (?, ?, ?)");
$stmt->execute(array(1, NULL, 'Categorie 1'));
$stmt->execute(array(2, NULL, 'Categorie 2'));
$stmt->execute(array(3, 2, 'Subcategorie 1'));
$stmt->execute(array(4, 2, 'Subcategorie 2'));
$stmt->execute(array(5, 4, 'SubSubCategorie 1'));
$stmt->execute(array(6, 4, 'SubSubCategorie 2'));
$stmt->execute(array(7, NULL, 'Categorie 3'));
return $pdo;
}
?>
- id
- parent_id
- title
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
$sql = "SELECT
men.title AS cat,
subMen.id AS subCatID,
subMen.title AS subCat
FROM
menu AS men
LEFT JOIN
menu AS subMen
ON
men.id = subMen.parent_id
WHERE
men.parent_id = 0
GROUP BY
subMen.id
ORDER BY
men.id,
subMen.title";
?>
$sql = "SELECT
men.title AS cat,
subMen.id AS subCatID,
subMen.title AS subCat
FROM
menu AS men
LEFT JOIN
menu AS subMen
ON
men.id = subMen.parent_id
WHERE
men.parent_id = 0
GROUP BY
subMen.id
ORDER BY
men.id,
subMen.title";
?>
Gewijzigd op 31/12/2010 15:13:11 door Milo S
Ontzettend bedankt