Ich habe mich nun entschieden, das Problem auf PHP-Seite anzupacken. Nach ein paar Stunden Gefrickel hatte ich eine funktionierende Version:
Dieses
Query liest den kompletten Navigationsbaum aus:
SQL-Code:
SELECT n.item_id, n.left_id, n.item_title, n.item_url, n.content_id, c.content_path,
(COUNT(p.item_id) - 1) AS level
FROM s2b_navigation_items n
INNER JOIN s2b_navigation_items p
ON n.left_id BETWEEN p.left_id AND p.right_id
LEFT JOIN s2b_content c
ON c.content_id = n.content_id
WHERE n.nav_id = 1
GROUP BY n.item_id
ORDER BY n.left_id
Das Ergebnis packe ich in ein Array
$tree, wobei die item_ids als Schlüssel verwendet werden.
Das zweite
Query liefert den Pfad zur aktuell ausgewählten Seite (in diesem Fall #2):
SQL-Code:
SELECT p.item_id, p.left_id, p.right_id, p.content_id
FROM s2b_navigation_items p
INNER JOIN s2b_navigation_items n
ON n.left_id BETWEEN p.left_id AND p.right_id
WHERE n.nav_id = 1
AND n.content_id = 2
ORDER BY p.left_id
Das Ergebnis speichere ich analog zu oben in ein Array
$path, zusätzlich werden die direkten Übereinstimmungen (= aktuell ausgewählte Seite) in ein separates Array
$selected gespeichert.
Anschließend generiere ich das Array $items, also die fertige Navigation, folgendermaßen:
Code:
$items = array();
foreach ($tree as $item_id => $item_data)
{
$item_level = $item_data['level'];
$item_left_id = $item_data['left_id'];
// Root-Ebene immer anzeigen
if ($item_level == 0)
{
$items[$item_id] = $item_data;
continue;
}
// Direkte Nachkommen der aktuellen Seite anzeigen (unterstützt mehrere Navigationspunkte für eine Seite)
foreach ($selected as $selected_id)
{
if ($item_left_id > $path[$selected_id]['left_id'] && $item_left_id < $path[$selected_id]['right_id'] && $item_level == $tree[$selected_id]['level'] + 1)
{
$items[$item_id] = $item_data;
continue 2;
}
}
// Nachbarelemente auf dem Pfad anzeigen
$last_id = null;
foreach ($path as $path_id => $path_data)
{
if (isset($last_id) && isset($tree[$path_id]))
{
if ($item_left_id > $path[$last_id]['left_id'] && $item_left_id < $path[$last_id]['right_id'] && $item_level == $tree[$path_id]['level'])
{
$items[$item_id] = $item_data;
continue 2;
}
}
$last_id = $path_id;
}
}
Zum Schluss wird das ganze über die Template-Engine ausgegeben - es funktioniert tadellos.