Waarom zie ik deze menuknop niet met dit script?
Nu wil ik deze functie alleen uitvoeren voor 1 knop, namelijk verhuur, en de rest wil ik zoals mijn oude menuscript.
Dus alleen wanneer er over verhuur wordt gehovered (cat_id 22) dan mag er een oneindig submenu uitklappen.
Ik heb op deze manier een poging gewaagd:
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?PHP
//Haal alle categorieen en check gelijk of de desbetreffende categorie artikelen onder zich heeft hangen.
$menu = "
SELECT cat.id as cat_id, cat.level, cat.parent_id, cat.title as cat_title, cat.alias as cat_alias, cat.published, cat.rgt, cnt.state, cnt.id as content_id, cnt.catid, cnt.title as content_title, cnt.alias as content_alias
FROM snm_categories cat
LEFT JOIN snm_content cnt
ON cnt.catid = cat.id
WHERE cat.id NOT IN (1, 2, 3, 4, 5, 7)
AND cat.published = 1
AND cat.level = 1
GROUP BY cat.id
ORDER BY cat.rgt ASC";
$menuconn = $conn->query($menu);
//Loop het resultaat
while($menu = $menuconn->fetch_assoc()){
$cat_ids = '';
$subcatmenulijst = '';
$subcats = '';
//Code om te checken of de huidige pagina gelijk is aan de alias
if($menu['alias'] == $alias){
$class='current';
} else {
$class = '';
}
//Stop alle ids van de categorieen in een array
$cat_ids[] = $menu['cat_id'];
//Implodeer ze met commas ertussen zodat ze bruikbaar zijn in een query
if(!empty($cat_ids)) {
$useableids = implode(',', $cat_ids);
}
// Query voor de subcats
$subcatmenu = 'SELECT * FROM snm_categories WHERE parent_id IN ('.$conn->real_escape_string($useableids).') and published = 1 ORDER BY lft';
$subcatmenucon = $conn->query($subcatmenu);
while($subcatmenu = $subcatmenucon->fetch_assoc()){
$subcatmenulijst .= '<li><a href="info/'.$subcatmenu['alias'].'.html">'.$subcatmenu['title'].'</a></li>';
}
// Als
if(!empty($subcatmenulijst)){
$subcats = 'true';
}
// Als het niet de `verhuur` knop is
if($menu['cat_id'] != 22){
//Loop alle categorieen
$menuresult .= '<li class="'.$class.'"><a href="info/'.$menu['cat_alias'].'.html">'.$menu['cat_title'].'</a>';
//Haal alle artikelen op waar het catid gelijk is aan het id van een categorie (binnen bovenstaande loop, zodat het gebeurd voor elke categorie)
$submenu = "SELECT * FROM snm_content WHERE catid = '".$conn->real_escape_string($menu['cat_id'])."' AND state = 1 ORDER BY ordering";
$submenuconn = $conn->query($submenu);
//Als er het id van een artikel niet leeg is (dus als er artikelen onder hangen) OF als er subcategorieeen aanwezig zijn:
if(!empty($menu['content_id']) OR $subcats == 'true'){
$menuresult .= '<ul class="sub-menu">';
//Loop het resultaat
while($submenu = $submenuconn->fetch_assoc()){
$menuresult .= '<li><a href="'.$submenu['alias'].'.html">'.$submenu['title'].'</a></li>';
}
// Plak de categorieen onder artikelen
$menuresult .= $subcatmenulijst;
$menuresult .= '</ul>';
}
// Maar als het dat wel is:
}else{
////
//Haal alle categorieen en check gelijk of de desbetreffende categorie artikelen onder zich heeft hangen.
$menucatalogus = "
SELECT cat.id as cat_id, cat.level, cat.parent_id, cat.title as cat_title, cat.alias as cat_alias, cat.published, cat.rgt
FROM snm_categories cat
WHERE cat.id NOT IN (1, 2, 3, 4, 5, 7)
AND cat.published = 1
GROUP BY cat.id
ORDER BY cat.rgt ASC";
$menucatalogusconn = $conn->query($menucatalogus);
$menuData = array(
'items' => array(),
'parents' => array()
);
// Maak een nieuwe array met simpelweg items en parents, welke gekoppeld zitten aan cat_id/parent_id
while($menucatalogus = $menucatalogusconn->fetch_assoc())
{
$menuData['items'][$menu['cat_id']] = $menu;
$menuData['parents'][$menu['parent_id']][] = $menu['cat_id'];
$arr[] = $menucatalogus;
}
// Functie om menu te maken, $parentId is 1 (de categorieen die geen parent hebben)
function buildMenu($parentId, $menuData)
{
//$menuresult = '';
if (isset($menuData['parents'][$parentId]))
{
//Als parent_id gelijk is aan 1 gooi een li eromheen (want het is geen subcat) anders een ul
if($parentId == '22'){
$menuresult = '<li>';
}else{
$menuresult = '<ul class="sub-menu">';
}
foreach ($menuData['parents'][$parentId] as $itemId)
{
$arrtje[] = $itemId;
$menuresult .= '<li class="menu-item"><a href="'.$menuData['items'][$itemId]['cat_alias'].'">'.$menuData['items'][$itemId]['cat_title'].'</a>';
// Voer deze functie uit binnen de functie loop (recursief)
$menuresult .= buildMenu($itemId, $menuData);
$menuresult .= '</li>';
}
//Als parent_id gelijk is aan 1 gooi een li eromheen (want het is geen subcat)
if($parentId == '22'){
$menuresult .= '</li>';
}else{
$menuresult .= '</ul>';
}
}
return $menuresult;
}
// Echo het resultaat van de functie en geef 1 mee als parent_id
echo buildMenu(1, $menuData);
////
}
$menuresult .= '</li>';
}
echo $menuresult;
?>
//Haal alle categorieen en check gelijk of de desbetreffende categorie artikelen onder zich heeft hangen.
$menu = "
SELECT cat.id as cat_id, cat.level, cat.parent_id, cat.title as cat_title, cat.alias as cat_alias, cat.published, cat.rgt, cnt.state, cnt.id as content_id, cnt.catid, cnt.title as content_title, cnt.alias as content_alias
FROM snm_categories cat
LEFT JOIN snm_content cnt
ON cnt.catid = cat.id
WHERE cat.id NOT IN (1, 2, 3, 4, 5, 7)
AND cat.published = 1
AND cat.level = 1
GROUP BY cat.id
ORDER BY cat.rgt ASC";
$menuconn = $conn->query($menu);
//Loop het resultaat
while($menu = $menuconn->fetch_assoc()){
$cat_ids = '';
$subcatmenulijst = '';
$subcats = '';
//Code om te checken of de huidige pagina gelijk is aan de alias
if($menu['alias'] == $alias){
$class='current';
} else {
$class = '';
}
//Stop alle ids van de categorieen in een array
$cat_ids[] = $menu['cat_id'];
//Implodeer ze met commas ertussen zodat ze bruikbaar zijn in een query
if(!empty($cat_ids)) {
$useableids = implode(',', $cat_ids);
}
// Query voor de subcats
$subcatmenu = 'SELECT * FROM snm_categories WHERE parent_id IN ('.$conn->real_escape_string($useableids).') and published = 1 ORDER BY lft';
$subcatmenucon = $conn->query($subcatmenu);
while($subcatmenu = $subcatmenucon->fetch_assoc()){
$subcatmenulijst .= '<li><a href="info/'.$subcatmenu['alias'].'.html">'.$subcatmenu['title'].'</a></li>';
}
// Als
if(!empty($subcatmenulijst)){
$subcats = 'true';
}
// Als het niet de `verhuur` knop is
if($menu['cat_id'] != 22){
//Loop alle categorieen
$menuresult .= '<li class="'.$class.'"><a href="info/'.$menu['cat_alias'].'.html">'.$menu['cat_title'].'</a>';
//Haal alle artikelen op waar het catid gelijk is aan het id van een categorie (binnen bovenstaande loop, zodat het gebeurd voor elke categorie)
$submenu = "SELECT * FROM snm_content WHERE catid = '".$conn->real_escape_string($menu['cat_id'])."' AND state = 1 ORDER BY ordering";
$submenuconn = $conn->query($submenu);
//Als er het id van een artikel niet leeg is (dus als er artikelen onder hangen) OF als er subcategorieeen aanwezig zijn:
if(!empty($menu['content_id']) OR $subcats == 'true'){
$menuresult .= '<ul class="sub-menu">';
//Loop het resultaat
while($submenu = $submenuconn->fetch_assoc()){
$menuresult .= '<li><a href="'.$submenu['alias'].'.html">'.$submenu['title'].'</a></li>';
}
// Plak de categorieen onder artikelen
$menuresult .= $subcatmenulijst;
$menuresult .= '</ul>';
}
// Maar als het dat wel is:
}else{
////
//Haal alle categorieen en check gelijk of de desbetreffende categorie artikelen onder zich heeft hangen.
$menucatalogus = "
SELECT cat.id as cat_id, cat.level, cat.parent_id, cat.title as cat_title, cat.alias as cat_alias, cat.published, cat.rgt
FROM snm_categories cat
WHERE cat.id NOT IN (1, 2, 3, 4, 5, 7)
AND cat.published = 1
GROUP BY cat.id
ORDER BY cat.rgt ASC";
$menucatalogusconn = $conn->query($menucatalogus);
$menuData = array(
'items' => array(),
'parents' => array()
);
// Maak een nieuwe array met simpelweg items en parents, welke gekoppeld zitten aan cat_id/parent_id
while($menucatalogus = $menucatalogusconn->fetch_assoc())
{
$menuData['items'][$menu['cat_id']] = $menu;
$menuData['parents'][$menu['parent_id']][] = $menu['cat_id'];
$arr[] = $menucatalogus;
}
// Functie om menu te maken, $parentId is 1 (de categorieen die geen parent hebben)
function buildMenu($parentId, $menuData)
{
//$menuresult = '';
if (isset($menuData['parents'][$parentId]))
{
//Als parent_id gelijk is aan 1 gooi een li eromheen (want het is geen subcat) anders een ul
if($parentId == '22'){
$menuresult = '<li>';
}else{
$menuresult = '<ul class="sub-menu">';
}
foreach ($menuData['parents'][$parentId] as $itemId)
{
$arrtje[] = $itemId;
$menuresult .= '<li class="menu-item"><a href="'.$menuData['items'][$itemId]['cat_alias'].'">'.$menuData['items'][$itemId]['cat_title'].'</a>';
// Voer deze functie uit binnen de functie loop (recursief)
$menuresult .= buildMenu($itemId, $menuData);
$menuresult .= '</li>';
}
//Als parent_id gelijk is aan 1 gooi een li eromheen (want het is geen subcat)
if($parentId == '22'){
$menuresult .= '</li>';
}else{
$menuresult .= '</ul>';
}
}
return $menuresult;
}
// Echo het resultaat van de functie en geef 1 mee als parent_id
echo buildMenu(1, $menuData);
////
}
$menuresult .= '</li>';
}
echo $menuresult;
?>
Dit laat alleen niet mijn knop 'verhuur' zien. Hoe komt dat?
Deze query:
This query:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
SELECT cat.id as cat_id, cat.level, cat.parent_id, cat.title as cat_title, cat.alias as cat_alias, cat.published, cat.rgt
FROM snm_categories cat
WHERE cat.id NOT IN (1, 2, 3, 4, 5, 7)
AND cat.published = 1
GROUP BY cat.id
ORDER BY cat.rgt ASC
FROM snm_categories cat
WHERE cat.id NOT IN (1, 2, 3, 4, 5, 7)
AND cat.published = 1
GROUP BY cat.id
ORDER BY cat.rgt ASC
bevat:
En deze query:
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
SELECT cat.id as cat_id, cat.level, cat.parent_id, cat.title as cat_title, cat.alias as cat_alias, cat.published, cat.rgt, cnt.state, cnt.id as content_id, cnt.catid, cnt.title as content_title, cnt.alias as content_alias
FROM snm_categories cat
LEFT JOIN snm_content cnt
ON cnt.catid = cat.id
WHERE cat.id NOT IN (1, 2, 3, 4, 5, 7)
AND cat.published = 1
AND cat.level = 1
GROUP BY cat.id
ORDER BY cat.rgt ASC
FROM snm_categories cat
LEFT JOIN snm_content cnt
ON cnt.catid = cat.id
WHERE cat.id NOT IN (1, 2, 3, 4, 5, 7)
AND cat.published = 1
AND cat.level = 1
GROUP BY cat.id
ORDER BY cat.rgt ASC
bevat:
Gewijzigd op 03/05/2018 15:48:12 door Snelle Jaap
Als je nu eerst eens functionaliteit maakt voor het bouwen van een generieke datastructuur (dit hoef je maar 1x te doen) en daarna je manipulaties toepast op deze datastructuur, of liever gezegd, op de weergave hiervan, scheelt je een hoop werk.
Nu ben je opnieuw een specifiek wiel aan het uitvinden, en daarmee maak je generieke code weer specifiek, dan ga je de verkeerde kant op.
Een eerste stap in de structurering hiervan is een soort van functie of verzameling van functies (of methoden in een klasse) voor het bouwen van een datastructuur die de boomstructuur van je site voorstelt. Als je dat eenmaal voor elkaar hebt (dat had je in principe al, wellicht niet helemaal op deze manier geformaliseerd?) dan kun je allerlei manipulaties gaan uitvoeren op deze gegenereerde boomstructuur, maar je hoeft dat ding dan dus niet elke keer from scratch op te trekken. Als je dat wel elke keer zou doen dan gaan er ook allerlei flarden code die ongeveer hetzelfde doen rondzwerven in je codebase. Dit wil je echt niet.
Bouw eerst die boom, en doe dan je ding met die gegenereerde boom.
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
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
<?PHP
$menu = "
SELECT cat.id as cat_id, cat.level, cat.parent_id, cat.title as cat_title, cat.alias as cat_alias, cat.published, cat.rgt, cnt.state, cnt.id as content_id, cnt.catid, cnt.title as content_title, cnt.alias as content_alias
FROM snm_categories cat
LEFT JOIN snm_content cnt
ON cnt.catid = cat.id
WHERE cat.id NOT IN (1, 2, 3, 4, 5, 7)
AND cat.published = 1
GROUP BY cat.id
ORDER BY cat.rgt ASC";
$menuconn = $conn->query($menu);
// Maak een nieuwe array om te vullen met onderstaand resultaat
$menuData = array(
'items' => array(),
'parents' => array()
);
// Maak een nieuwe array met simpelweg items en parents, welke gekoppeld zitten aan cat_id/parent_id
while($menu = $menuconn->fetch_assoc())
{
$menuData['items'][$menu['cat_id']] = $menu;
$menuData['parents'][$menu['parent_id']][] = $menu['cat_id'];
}
// Functie om menu te maken, $parentId is 1 (de categorieen die geen parent hebben)
function buildMenu($parentId, $menuData)
{
$html = '';
if (isset($menuData['parents'][$parentId]))
{
//Als parent_id gelijk is aan 1 gooi een li eromheen (want het is geen subcat) anders een ul
if($parentId == '1'){
$html = '<li>';
}else{
$html = '<ul class="sub-menu">';
}
foreach ($menuData['parents'][$parentId] as $itemId)
{
$html .= '<li class="menu-item"><a href="'.$menuData['items'][$itemId]['cat_alias'].'">'.$menuData['items'][$itemId]['cat_title'].'</a>';
// Voer deze functie uit binnen de functie loop (recursief)
$html .= buildMenu($itemId, $menuData);
$html .= '</li>';
}
//Als parent_id gelijk is aan 1 gooi een li eromheen (want het is geen subcat)
if($parentId == '1'){
$html .= '</li>';
}else{
$html .= '</ul>';
}
}
return $html;
}
// Echo het resultaat van de functie en geef 1 mee als parent_id
echo buildMenu(1, $menuData);
?>
$menu = "
SELECT cat.id as cat_id, cat.level, cat.parent_id, cat.title as cat_title, cat.alias as cat_alias, cat.published, cat.rgt, cnt.state, cnt.id as content_id, cnt.catid, cnt.title as content_title, cnt.alias as content_alias
FROM snm_categories cat
LEFT JOIN snm_content cnt
ON cnt.catid = cat.id
WHERE cat.id NOT IN (1, 2, 3, 4, 5, 7)
AND cat.published = 1
GROUP BY cat.id
ORDER BY cat.rgt ASC";
$menuconn = $conn->query($menu);
// Maak een nieuwe array om te vullen met onderstaand resultaat
$menuData = array(
'items' => array(),
'parents' => array()
);
// Maak een nieuwe array met simpelweg items en parents, welke gekoppeld zitten aan cat_id/parent_id
while($menu = $menuconn->fetch_assoc())
{
$menuData['items'][$menu['cat_id']] = $menu;
$menuData['parents'][$menu['parent_id']][] = $menu['cat_id'];
}
// Functie om menu te maken, $parentId is 1 (de categorieen die geen parent hebben)
function buildMenu($parentId, $menuData)
{
$html = '';
if (isset($menuData['parents'][$parentId]))
{
//Als parent_id gelijk is aan 1 gooi een li eromheen (want het is geen subcat) anders een ul
if($parentId == '1'){
$html = '<li>';
}else{
$html = '<ul class="sub-menu">';
}
foreach ($menuData['parents'][$parentId] as $itemId)
{
$html .= '<li class="menu-item"><a href="'.$menuData['items'][$itemId]['cat_alias'].'">'.$menuData['items'][$itemId]['cat_title'].'</a>';
// Voer deze functie uit binnen de functie loop (recursief)
$html .= buildMenu($itemId, $menuData);
$html .= '</li>';
}
//Als parent_id gelijk is aan 1 gooi een li eromheen (want het is geen subcat)
if($parentId == '1'){
$html .= '</li>';
}else{
$html .= '</ul>';
}
}
return $html;
}
// Echo het resultaat van de functie en geef 1 mee als parent_id
echo buildMenu(1, $menuData);
?>
Heeft qua data alles wat ik nodig heb. Alleen hoe kan ik makkelijk onderscheid maken?
Mijn huidige menu (bovenstaande code) heeft alleen maar categorieen en subcategorieen. Maar ik heb naast die categorieen nog één optie, een artikel die onder een categorie kan hangen.
Dus: een categorie kan aan een categorie hangen en wordt dus een subcategorie in mijn menu. Maar een artikel kan ook aan een categorie gehangen worden, maar weer niet aan een ander artikel, je hebt dus geen sub artikelen.
De structuur is als volgt:
snm_categories (de categorieen)
id - id van de categorie
parent_id id van de categorie waar deze categorie onder hangt, 1 als hij geen parent heeft
snm_content (de artikelen)
id - het id van het artikel
catid - het id van de categorie waar die aanhangt (zelfde als id bij snm_categories)
Met de artikelen gebeurt er nu nog niks in mijn menu script, maar de data haal ik wel op met mijn query.
Ik wil voor de artikelen een andere link dan voor de categorieen zodat deze via .htaccess doorverwijst naar een andere page.
Kan dat met mijn huidige script of zal ik deze compleet moeten ombouwen?
Quote:
Dit laat alleen niet mijn knop 'verhuur' zien. Hoe komt dat?
Mogelijk vanwege het volgende:
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
<?php
while($menu = $menuconn->fetch_assoc()){ // regel 15
$cat_ids = ''; // regel 16
// ...
$cat_ids[] = $menu['cat_id']; // regel 27
// ...
}
?>
while($menu = $menuconn->fetch_assoc()){ // regel 15
$cat_ids = ''; // regel 16
// ...
$cat_ids[] = $menu['cat_id']; // regel 27
// ...
}
?>
Oftewel: elke stap in de while-loop kieper je doodleuk $cat_ids leeg.
Daarnaast: nog een query in een while-loop? Waar is dat voor nodig? De hele menu-opbouw kan met één (of twee, voor de artikelen wellicht) queries.
Maar ook: een functiedeclaratie in een while-loop? Krijg je daar geen foutmeldingen over?
Quote:
Kan dat met mijn huidige script of zal ik deze compleet moeten ombouwen?
Hm - je zou een aparte entry "articles" kunnen aanmaken in je datastructuur? Daarnaast is wellicht een betere benaming voor "parents" "children" want het betreft nazaten (onderliggende elementen), geen ouders (bovenliggende elementen).
Ik zou dit dus opsplitsen:
stap 1: bouw (op een efficiënte manier) een datastructuur waar ALLES in zit, ook al heb je specifieke wensen.
stap 2: bouw de HTML-menu's waarin je specifieke dingen eruitfiltert of juist laat zien op grond van de boom uit stap 1 waarin alles zit.
De functie staat in een else-blok, dus zolang de conditie ervoor zorgt dat dat else-blok maar 1x wordt aangeroepen, gaat het goed. Als er echter twee menu-opties zijn met cat_id == 22, krijg je een redeclaration error.
Willem vp op 04/05/2018 14:42:50:
De functie staat in een else-blok, dus zolang de conditie ervoor zorgt dat dat else-blok maar 1x wordt aangeroepen, gaat het goed. Als er echter twee menu-opties zijn met cat_id == 22, krijg je een redeclaration error.
Akkoord, maar simpelweg omdat iets werkt maakt het nog niet juist :).