Hallo allemaal,
Ik ben een code aan het omzetten van een HTML code naar een PHP die alles uit een database haalt.
De code bevat een stukje de het menu moet tonen. Met behulp van <li> en <lu>
Nu lukt het mij niet om de submenu's er in te krijgen.
Hieronder staan eerst de HTML code zoals die is, dan hoe die door de PHP code wordt gemaakt en als derde de php code die de html code moet maken.
Oef, dit is een flinke toren van query's (want ze worden massaal vermenigvuldigd met loopjes in loopjes) waar op zijn minst gezegd niet echt zuinig mee wordt omgegaan. ;-)
Ik weet zeker dat je hier beter naar recursie kan kijken, en een minimalisatie van het aantal queries.
Laten we dit voorbeeld van structuur eens aanhouden, om je menu's mee op te stellen, waarbij feitelijk oneindig veel levels kan maken.
id parentId name
1 0 Auto's
2 0 Fietsen
3 0 Vrachtwagens
4 1 Audi
5 1 BMW
6 5 Z3
Dan loont het om de boel met een enkele query op te halen, de array samen te stellen, en met een aparte functie de recursie toe te passen:
<?php
// get all menuitems with 1 query
$result = $conn->query("
SELECT
id, parentId, name
FROM
menu
ORDER BY
parentId, name
");
// prepare special array with parent-child relations
$menuData = array(
'items' => array(),
'parents' => array()
);
while ($menuItem = $result->fetch_assoc())
{
$menuData['items'][$menuItem['id']] = $menuItem;
$menuData['parents'][$menuItem['parentId']][] = $menuItem['id'];
}
// menu builder function, parentId 0 is the root
function buildMenu($parentId, $menuData)
{
$html = '';
if (isset($menuData['parents'][$parentId]))
{
$html = '<ul>';
foreach ($menuData['parents'][$parentId] as $itemId)
{
$html .= '<li>' . $menuData['items'][$itemId]['name'];
// find childitems recursively
$html .= buildMenu($itemId, $menuData);
$html .= '</li>';
}
$html .= '</ul>';
}
return $html;
}
// output the menu
echo buildMenu(0, $menuData);
?>
Hmm, het zou misschien nog handig zijn om een volgorde toe te voegen, zodat je zelf kunt bepalen op welke positie een item staat. Mogelijk is het afdoende dat je op naam sorteert, maar daarmee offer je configureerbaarheid op. Deze extra functionaliteit is makkelijk toe te voegen.
Mogelijke andere optimalisaties: output escaping, en output buffering i.p.v. HTML breien.
Heel erg bedankt voor het meedenken, maar ik kom er toch nog niet uit.
Bij mij werkte het niet direct, en ik moest dus vogelen om het wel werkend te krijgen. Ik kwam daar niet uit.
Ik begin niet met <ul> omdat die afwijkt van alle <ul>s die ik verder nog heb.
Dus ik moet beginnen met <li> en dan later als er een sub is moet ik de </li> uitstellen tot na de zoveelste </ul>
Ik heb aan het begin wel bedacht dat ik de volgorde in sql kan bepalen.
$menu_result = $connect->query("SELECT * FROM tabel_menu ORDER BY menu_sub_van, menu_waarde");
Van daar uit zal ik het denk ik naar een array moeten zetten, om de verschillende niveaus van de menu's te onderscheiden van elkaar. Ik ben niet zo thuis in het gebruik van foreach(...){...}
Hoeveel kan ik in een variabele stoppen?
Want ik dacht een array te moeten gebruiken om iedere regel in een eigen (array-)variabele te zetten. Maar als ik de code van -Ariën- bekijk, dan denk ik dat ik zie dat de variabele html gevuld wordt, en dat die vervolgens in het html deel getoond kan worden.
Ik begin niet met <ul> omdat die afwijkt van alle <ul>s die ik verder nog heb.
Dus ik moet beginnen met <li> en dan later als er een sub is moet ik de </li> uitstellen tot na de zoveelste </ul>
Je bedoelt dat de styling afwijkt? Dan moet je de styling aanpassen. een <li> hoort gewoon in een <ul>.
Een foreach is niks meer dan een loop, waarmee je door een array kan wandelen.
Hoe je zo'n array genereert uit database resultaten kan met mysqli_fetch_array of als je hier zelf controle over wilt moet je deze zelf opbouwen, zoals in het voorbeeld van Arien regel 18 tm 22.
hahaha nee dat snap ik. Daar werk ik later wel aan. Het ging hier om de werking van het menu.
Nogmaals Heel erg bedankt. Vooral voor het inzicht wat je me gaf.
Nu dacht ik het voor elkaar te hebben, maar helaas.
Ik had 3 items in het hoofmenu. Alleen de tweede had een submenu. Ik zet verander ook de derde naar een menu-item met submenu, en nu verschijnt alleen het hoofdmenu-item.
Als ik er een vierde hoofdmenu-item aan toevoeg, werkt dat wel.
Ik zie nu niet wat ik fout heb gedaan.
<?php // *** menu ****
$result = $connect->query("SELECT * FROM tabel_menu ORDER BY menu_sub_van, menu_waarde");
// prepare special array with parent-child relations
$menuData = array(
'items' => array(),
'parents' => array()
);
while ($menuItem = $result->fetch_assoc())
{
$menuData['items'][$menuItem['menu_id']] = $menuItem;
$menuData['parents'][$menuItem['menu_sub_van']][] = $menuItem['menu_id'];
}
// menu builder function, parentId 0 is the root
function buildMenu($parentId, $menuData)
{
$html = '';
if (isset($menuData['parents'][$parentId]))
{
if ($parentId==0)
{
$html = '<ul class="art-hmenu">';
}
else
{
$html = '<ul>';
}
foreach ($menuData['parents'][$parentId] as $itemId)
{
$html .= '<li><a href="">' . $menuData['items'][$itemId]['menu_tekst'] . '</a>';
// find childitems recursively
$html .= buildMenu($itemId, $menuData);
$html .= '</li>';
}
$html .= '</ul>';
}
return $html;
}
// output the menu
?>
<nav class="art-nav">
<?php
echo buildMenu(0, $menuData);
?>
</ul>
</nav>
<?php // *** einde menu ****
?>