In mijn CMS'je haal ik op elke pagina een navigatie-boom op met behulp van een recursieve functie. Voor ik deze functie aanroep, bepaal ik de array van elementen uit de boom die 'opengeklapt' moeten zijn. Ga er hier van uit dat die array, $path genaamd, er als volgt uitziet:
Vervolgens roep ik de recursieve functie aan met setSubmenu(55, '/cms'):
Dit geeft de volgende output:
Maar nu bedacht ik me ineens - het is onzin om in setSubmenu 5 queries af te draaien. Ik kan immers:
vervangen door
en zo vele queries uitsparen. Ik heb hierover twee vragen:
• MySQL schijnt niet zo sterk te zijn in subqueries; is de tweede optie beter dan hoe het nu werkt?
• Wie kan mij een start geven met hoe ik de resultset van die tweede query in een gelijke boom zet. Ik heb namelijk geen idee hoe te beginnen...
code:
1
2
3
4
5
6
7
8
| Array ( [0] => 76 <-- node waar we nu zijn [1] => 73 [2] => 70 [3] => 68 [4] => 55 <-- root ) |
Vervolgens roep ik de recursieve functie aan met setSubmenu(55, '/cms'):
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
| function setSubmenu($parent, $parentUrl, $level=0) { global $menu, $path, $trail, $nodes; if ($level != 0) { $endul = '</ul></li>'; } else { $endul = '</ul>'; } $res_menu = db_query('SELECT node_id, node_name, node_pos FROM nodes WHERE node_pid = %d ORDER BY node_pos ASC', $parent); if (db_num_rows($res_menu) == 0) { $menu .= '</li>'; } else { $menu .= '<ul>'; for ($a=0; $a<db_num_rows($res_menu); $a++) { $row_menu = db_fetch_array($res_menu); $state = ''; if(in_array ($row_menu['node_id'], $path)) { $class = $level.'-on'; $endli = ''; if ((count($path)-1) != $level) { $trail.= ' > <a href="'.$parentUrl.'/'. $row_menu['node_name'].'">'. $row_menu['node_name'].'</a>'; } else { $trail .= ' > '.$row_menu['node_name']; $state = '-sel'; } } else { $class = $level.'-off'; $endli = '</li>'; } $menu .= '<li class="'.$class.$state.'"><a href="'.$parentUrl.'/'. $row_menu['node_name'].'/">'. $row_menu['node_name'].'</a>'. $endli; if(in_array ($row_menu['node_id'], $path)) { $newParent = $parentUrl.'/'.arg($level); setSubmenu($row_menu['node_id'],$newParent, $level+1); } } $menu .= $endul; return $menu; } } |
Dit geeft de volgende output:
HTML:
1
2
3
4
5
6
7
8
9
10
| over_kwispel
abonnementen
bejaarden
mannen
vrouwen
mooi
lelijk <!-- we zijn hier
jongeren
contact
diensten |
Maar nu bedacht ik me ineens - het is onzin om in setSubmenu 5 queries af te draaien. Ik kan immers:
code:
1
2
3
4
5
| SELECT node_id, node_name, node_pos FROM nodes WHERE node_pid = 55 ORDER BY node_pos ASC SELECT node_id, node_name, node_pos FROM nodes WHERE node_pid = 68 ORDER BY node_pos ASC SELECT node_id, node_name, node_pos FROM nodes WHERE node_pid = 70 ORDER BY node_pos ASC SELECT node_id, node_name, node_pos FROM nodes WHERE node_pid = 73 ORDER BY node_pos ASC SELECT node_id, node_name, node_pos FROM nodes WHERE node_pid = 76 ORDER BY node_pos ASC |
vervangen door
code:
1
2
3
4
5
| SELECT node_id, node_name, node_pos FROM nodes WHERE node_pid IN ( 55, 68, 70, 73, 76 ) ORDER BY node_pos ASC |
en zo vele queries uitsparen. Ik heb hierover twee vragen:
• MySQL schijnt niet zo sterk te zijn in subqueries; is de tweede optie beter dan hoe het nu werkt?
• Wie kan mij een start geven met hoe ik de resultset van die tweede query in een gelijke boom zet. Ik heb namelijk geen idee hoe te beginnen...
"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."