Die "perfekte" PHP-Navigation
botl1k3
- php
0 Auge0 Sympatisant0 botl1k30 Sympatisant
Hallo,
ich bim im Moment dabei, eine Website zu erstellen, die in zwei Navigationen aufgeteilt wird: Oberkategorien und Unter-(unter-)Kategorien.
Ich möchte die Navigation jetzt via PHP realisieren, sodass ich im Code (oder wo auch immer) die Navigation festlegt und der Code dann die Navigation automatisch anpasst (nur Unterkategorien der Oberkategorie anzeigen, Unter-unter- Kategorien ausklappen und den aktuellen Menüpunkt mit CSS highlighten).
Ich kann PHP einigermaßen, mein Problem ist aber, das mir der Ansatz fehlt, wie ich das Menü deklarieren soll, damit ich es "leicht und performant" auslesen kann ;)
Soll ich mehrdimensionale Arrays erstellen (würde warscheinlich auf 3 dimensional hinauslaufen, oder die Menüpunkte aus einer Textdatei auslesen? Ich weiß nicht wie ich soetwas am praktischten erledigen kann, ein Denkanstoß wäre nett..
Gruß,
botl1k3
Hallo
ich bim im Moment dabei, eine Website zu erstellen, die in zwei Navigationen aufgeteilt wird: Oberkategorien und Unter-(unter-)Kategorien.
Ich möchte die Navigation jetzt via PHP realisieren, sodass ich im Code (oder wo auch immer) die Navigation festlegt und der Code dann die Navigation automatisch anpasst (nur Unterkategorien der Oberkategorie anzeigen, Unter-unter- Kategorien ausklappen und den aktuellen Menüpunkt mit CSS highlighten).
Ich kann PHP einigermaßen, mein Problem ist aber, das mir der Ansatz fehlt, wie ich das Menü deklarieren soll, damit ich es "leicht und performant" auslesen kann ;)
Soll ich mehrdimensionale Arrays erstellen (würde warscheinlich auf 3 dimensional hinauslaufen, oder die Menüpunkte aus einer Textdatei auslesen? Ich weiß nicht wie ich soetwas am praktischten erledigen kann, ein Denkanstoß wäre nett..
Ich würde es mit einem mehrdimensionalen Array machen. Das ist mMn die logische Wahl, da es Gruppen und Gruppen, die Kinder von Gruppen sind, gibt. Zudem kannst du mit einer lokal absoluten Pfadangabe ab DOCUMENT ROOT (z.B. "/unterverzeichnis/datei.html") auch gleich prüfen, ob der aktuell auszugebende Menüpunkt $_SERVER["SCRIPT_NAME"]
entspricht, also die aktuell geladene Datei ist und somit _nicht_ als Link ausgegeben werden muss.
Übrigens, wenn du die angesprochenen Textdateien nicht einfach nur als HTML-Templates verwendet, liest du sie (höchstwahrscheinlich) auch nur als Array ein. ;-)
Tschö, Auge
Hi,
Ich würde es mit einem mehrdimensionalen Array machen. Das ist mMn die logische Wahl, da es Gruppen und Gruppen, die Kinder von Gruppen sind, gibt. Zudem kannst du mit einer lokal absoluten Pfadangabe ab DOCUMENT ROOT (z.B. "/unterverzeichnis/datei.html") auch gleich prüfen, ob der aktuell auszugebende Menüpunkt
$_SERVER["SCRIPT_NAME"]
entspricht, also die aktuell geladene Datei ist und somit _nicht_ als Link ausgegeben werden muss.
Okay, dann würde eine Gruppe mit Unterpunkten so aussehen:
[code lang=php]$nav = array(
array( # Oberkategorie
'Home',
'/index.php',
array( # Erste Untergruppe Home
'Unter 1',
'unter1.php',
array( # Unter-untergruppen
'Unter-unter 1-1',
'unterunter1_1.php'
),
array( # Unter-untergruppen
'Unter-unter 1-2',
'unterunter1_2.php'
)
),
array( # Zweite Untergruppe Home
'Unter 2',
'unter2.php',
array( # Unter-untergruppen
'Unter-unter 2-1',
'unterunter2_1.php'
),
array( # Unter-untergruppen
'Unter-unter 2-2',
'unterunter2_2.php'
)
)
),
array( # Oberkategorie
'Ober 2',
'/index.php',
array( # Erste Untergruppe Ober 2
'Unter 1',
'unter1.php',
array( # Unter-untergruppen
'UU Ober 1-1',
'uuober1_1.php'
),
array( # Unter-untergruppen
'UU Ober 1-2',
'uuober1_2.php'
)
)
)[/code}
So soll ich das machen?
Gruß
Hallo
Ich würde es mit einem mehrdimensionalen Array machen. ...
Okay, dann würde eine Gruppe mit Unterpunkten so aussehen:
$nav = array(
array( # Oberkategorie
'Home',
'/index.php',
array( # Erste Untergruppe Home
'Unter 1',
'unter1.php',
array( # Unter-untergruppen
'Unter-unter 1-1',
'unterunter1_1.php'
),
array( # Unter-untergruppen
'Unter-unter 1-2',
'unterunter1_2.php'
)
)
)
...
)
>
> So soll ich das machen?
Gucken wir mal bei mir, wenn auch eindimensional und als assoziatives Array:
~~~php
$navi = array(
array("url"=>"/index.php","text"=>"Übersicht"),
array("url"=>"/ausgaben/index.php","text"=>"Ausgabenliste","query"=>"SELECT COUNT(*) AS eintraege FROM ausgaben"));
Ich arbeite demnach mit lokal absoluten Pfaden, damit in jeglichem Verzeichnis, in dem das Menü in einem Dokument eingebaut wird, die Verzeichnishierarchie stimmt. Den Query lassen wir mal außen vor und die benamsten Schlüssel sind mir lieber, damit, falls ich irgendwann eine Änderung an der Struktur des Arrays vornehme, der Code, der das Array verwendet, nicht geändert werden muss. $navi[0]["url"]
wird immer die URL enthalten, egal ob es das erste oder das dritte Element von $navi[0]
ist.
Ansonsten, ja, so kann man es machen.
Tschö, Auge
Ansonsten, ja, so kann man es machen.
hab ich auch bereits mal so gelöst - in einer schleife lässt sich das dann problemlos in eine unsortierte liste übertragen
ggf solltest du aber noch eine information bereitstelle, welcher menupunkt aktuell aktiv ist (ausserhalb des arrays als variable mit zusatzinfo)
das ist praktisch, da mann dann aus dem selben array den seitentitel beziehen kann, oder eine breadcrumb-navigation erstellen kann
Hallo
Ansonsten, ja, so kann man es machen.
hab ich auch bereits mal so gelöst - in einer schleife lässt sich das dann problemlos in eine unsortierte liste übertragen
ggf solltest du aber noch eine information bereitstelle, welcher menupunkt aktuell aktiv ist (ausserhalb des arrays als variable mit zusatzinfo)
Wie man per Vergleich mit $_SERVER["SCRIPT_NAME"]
da ran kommt, habe ich ja schon angedeutet. Mit dieser Information außerhalb der Schleife weiterzuarbeiten, sollte dann kein Problem mehr darstellen.
das ist praktisch, da mann dann aus dem selben array den seitentitel beziehen kann, oder eine breadcrumb-navigation erstellen kann.
Ja, eine feine Erweiterung. :-)
Tschö, Auge
Moin,
$navi = array(
array("url"=>"/index.php","text"=>"Übersicht"),
array("url"=>"/ausgaben/index.php","text"=>"Ausgabenliste","query"=>"SELECT COUNT(*) AS eintraege FROM ausgaben"));
Bis auf die Namensgebung besteht also kein Unterschied, oder? Also in deinem Fall müsste ich dann wo deine query steht eben wieder ein Array einsetzen falls Unterpunkte da sind, richtig?
Gruß
Hallo
$navi = array(
array("url"=>"/index.php","text"=>"Übersicht"),
array("url"=>"/ausgaben/index.php","text"=>"Ausgabenliste","query"=>"SELECT COUNT(*) AS eintraege FROM ausgaben"));
>
> Bis auf die Namensgebung besteht also kein Unterschied, oder? Also in deinem Fall müsste ich dann wo deine query steht eben wieder ein Array einsetzen falls Unterpunkte da sind, richtig?
Ja, in der Schleife erfolgt dann eine Abfrage, ob da noch weitere Arrays sind und gegebenenfalls eine entsprechende Verarbeitung. Bedenke aber den Pfadaufbau, so du mit Unterverzeichnissen arbeitest! Nicht, dass du morgen mit "Das Menü wird ausgegeben, aber in einem Unterverzeichnis passen die Pfade nicht." ankommst. :-)
Tschö, Auge
--
Die deutschen Interessen werden am Liechtenstein verteidigt.
[Veranstaltungsdatenbank Vdb 0.2](http://termindbase.auge8472.de/)
Hi,
Ja, in der Schleife erfolgt dann eine Abfrage, ob da noch weitere Arrays sind und gegebenenfalls eine entsprechende Verarbeitung. Bedenke aber den Pfadaufbau, so du mit Unterverzeichnissen arbeitest! Nicht, dass du morgen mit "Das Menü wird ausgegeben, aber in einem Unterverzeichnis passen die Pfade nicht." ankommst. :-)
nenene ;)
Wobei sich mir grade eine Frage stellt:
Wenn ich mit der Namensgebung arbeite, dann hab ich z.B. 'caption' =>, 'url' =>, ... ok, jetzt habe ich aber mehrere Untermenüs, dann hab ich ja nicht mehr mit 'subs' => arbeiten, außer ich packe die nochmal um ein Array (siehe Code oben). Verstehst Du was ich meine?
Gruß
Hallo
Hi,
Ja, in der Schleife erfolgt dann eine Abfrage, ob da noch weitere Arrays sind und gegebenenfalls eine entsprechende Verarbeitung. Bedenke aber den Pfadaufbau, so du mit Unterverzeichnissen arbeitest! Nicht, dass du morgen mit "Das Menü wird ausgegeben, aber in einem Unterverzeichnis passen die Pfade nicht." ankommst. :-)
nenene ;)
Wobei sich mir grade eine Frage stellt:
Wenn ich mit der Namensgebung arbeite, dann hab ich z.B. 'caption' =>, 'url' =>, ... ok, jetzt habe ich aber mehrere Untermenüs, dann hab ich ja nicht mehr mit 'subs' => arbeiten, außer ich packe die nochmal um ein Array (siehe Code oben). Verstehst Du was ich meine?
Das Array mit einer Untermenüebene:
$navi = array(
array("url"=>"/index.php","text"="Startseite"),
array("url"=>"/punkt1/index.php","text"="Punkt 1"),
array("url"=>"/punkt2/index.php","text"="Punkt 2","sub"=>
array(array("url"=>"/punkt2/punkt21.php","text"="Punkt 2.1"),
array(array("url"=>"/punkt2/punkt22.php","text"="Punkt 2.2"))),
array("url"=>"/impressum.php","text"="Impressum"));
Auswertung:
function meine_navigation($navi) {
$ret = "<ul>\n";
foreach ($navi as $val)
{
$ret .= "<li><a href=\"".$val["url"]."\">".$val["text"]."</a>";
if (isset($val["sub"]))
{
$ret .= meine_navigation($navi);
}
$ret .= "</li>\n";
}
$return = "</ul>\n";
return $ret;
}
Achtung: ungetestet!
sollte folgendes ergeben:
-Startseite
-Punkt 1
-Punkt 2
-Punkt 2.1
-Punkt 2.2
-Impressum
Tschö, Auge
Hi,
Das Array mit einer Untermenüebene:
$navi = array(
array("url"=>"/index.php","text"="Startseite"),
array("url"=>"/punkt1/index.php","text"="Punkt 1"),
array("url"=>"/punkt2/index.php","text"="Punkt 2","sub"=>
array(array("url"=>"/punkt2/punkt21.php","text"="Punkt 2.1"),
array(array("url"=>"/punkt2/punkt22.php","text"="Punkt 2.2"))),
array("url"=>"/impressum.php","text"="Impressum"));
Im Sub ist ein Array zu viel, also es müsste doch heißen
~~~php
sub => array(
array(punkt 2.1),
array(punk 2.2)
)
richtig?
Dann ist meine Frage beantwortet, ich wollte nähmlich genau das wissen, ob die Unterpunkt-Arrays nochmal von einem Array ummantelt werden müssen (ja).
Danke!!
Gruß
Hallo
Das Array mit einer Untermenüebene:
$navi = array(
array("url"=>"/index.php","text"="Startseite"),
array("url"=>"/punkt1/index.php","text"="Punkt 1"),
array("url"=>"/punkt2/index.php","text"="Punkt 2","sub"=>
array(array("url"=>"/punkt2/punkt21.php","text"="Punkt 2.1"),
array(array("url"=>"/punkt2/punkt22.php","text"="Punkt 2.2"))),
array("url"=>"/impressum.php","text"="Impressum"));
>
> Im Sub ist ein Array zu viel, also es müsste doch heißen
> ~~~php
sub => array(
> array(punkt 2.1),
> array(punk 2.2)
> )
richtig?
Wenn die URLs etc. eingefügt werden, ja.
...
array("url"=>"/punkt2/index.php","text"="Punkt 2","sub"=>
array(
array("url"=>"/punkt2/punkt21.php","text"="Punkt 2.1"),
array("url"=>"/punkt2/punkt22.php","text"="Punkt 2.2")),
array("url"=>"/impressum.php","text"="Impressum"));
Tschö, Auge
function meine_navigation($navi) {
$ret .= meine_navigation($navi);
}
> Achtung: ungetestet!
huiii - endlosschleife
meine\_navigation($val['sub']);
ist wohl besser geeignet ;)
Hi,
array( # Oberkategorie
'Home',
'/index.php',
array( # Erste Untergruppe Home
die Startseite (die ich bei deutschsprachigen Seiten auch nicht so benennen würde) hat doch eigentlich keine Unterseiten.
'Unter 1',
'unter1.php',
Thema sprechende URLs: die Doppelung muss nicht sein. Du kannst aus dem Linktext "Unter 1" bequem einen URL-Parameter "Unter_1" und einen Dateinamen "Unter_1.inc" generieren - oder die Datei einfach gleich dem URL-Parameter benennen.
freundliche Grüße
Ingo
Hi,
Thema sprechende URLs: die Doppelung muss nicht sein. Du kannst aus dem Linktext "Unter 1" bequem einen URL-Parameter "Unter_1" und einen Dateinamen "Unter_1.inc" generieren - oder die Datei einfach gleich dem URL-Parameter benennen.
Könnte man machen, jedoch wird es warscheinlich Link-Titel geben die ich dann im Dateinamen "abkürzen" werde.
Gruß
Hi,
Könnte man machen, jedoch wird es warscheinlich Link-Titel geben die ich dann im Dateinamen "abkürzen" werde.
und warum? Das spart rein gar nichts, sondern macht im Gegenteil nur mehr Schreibarbeit und vergrößert das Array.
Die 8.3-Zeiten sind doch längst Geschichte...
freundliche Grüße
Ingo
Hi,
Die 8.3-Zeiten sind doch längst Geschichte...
Das stimmt wohl, doch möchte ich keine Dateinamen á la "bauen_sie_jetzt_ihre_eigene_tolle_php_navigation.php"
Ok, so schlimm werden die Links warscheinlich nicht werden, aber Du verstehst was ich meine?
Gruß
Hi,
Das stimmt wohl, doch möchte ich keine Dateinamen á la "bauen_sie_jetzt_ihre_eigene_tolle_php_navigation.php"
Ok, so schlimm werden die Links warscheinlich nicht werden, aber Du verstehst was ich meine?
nicht ganz. Denn solche extremen URL-Parameter würden mich ebenso stören.
freundliche Grüße
Ingo
Hallo botl1k3,
erstelle dir doch eine Klasse "Menu", welche eine Liste von "MenuItems"
enthaelt. Jedes MenuItem selbst besitzt schliesslich auch noch eine
Liste von MenuItems.
Beim Aufbau des Menues kannst du dann rekursiv durch die einzelnen
Items iterieren.
Der Containerklasse "Menu" kannst du dann ja beliebig viele Attribute
zuweisen; wie zB das gerade aktive MenuElement etc..
MfG,
Sympatisant
Hi,
erstelle dir doch eine Klasse "Menu", welche eine Liste von "MenuItems"
enthaelt. Jedes MenuItem selbst besitzt schliesslich auch noch eine
Liste von MenuItems.
Beim Aufbau des Menues kannst du dann rekursiv durch die einzelnen
Items iterieren.
Der Containerklasse "Menu" kannst du dann ja beliebig viele Attribute
zuweisen; wie zB das gerade aktive MenuElement etc..
Hi,
hab in PHP noch nie mit Klassen gearbeitet. Du meinst also ich soll 2 Klasse erstellen?
einmal Menu: Array aus MenuItems
und MenuItem: Kann 2 Strings und ein Array aufnehmen (sagen wir 'caption', 'url' und 'subs' als Array
Da ich soetwas noch nie gemacht habe, wie schreibt man sowas?
Gruß
Salvete,
Nur mal so als Denkanstoss - kann man natuerlich beliebig variieren:
// Ein Menu-Item
public class MenuItem
{
protected $SubItems; // Sub-Array of MenuItems
public $Url;
public $Text;
public $ToolTip;
// etc.. alle benoetigten Eigenschaften
public function GetItems() { .. }
public function AddItem($MenuItem) { ... }
public function SetItems($arrMenuItems) { ... }
}
// Das Menu
public class Menu
{
protected $Items; // recursie array of MenuItems
public function GetItems() {
return $this->Items;
}
public function AddItem($MenuItem) {
if($MenuItem instanceof MenuItem)
array_push($this->Items, $MenuItem);
}
public function SetItems($arrMenuItems) {
$this->Items = $arrMenuItems;
}
public function GetCurrent() {[...] }
public function SetCurrent($MenuItem) {[...] }
public function DoSomeMenuOperations() { [...] }
// saemtliche Methoden die due fuer ein Menu benoetigst
[...]
// das Menu koennte sich auch selbst zusammenbauen
public function BuildMenu($MenutItem=$this->$Items) {
$htmlMenu = '<ul>';
foreach($this->Items as $Item) {
$htmlMenu .= '<li> <a href='.$Item->Url.' title='.$Item->ToolTip.'>'.$Item->Text.'</a></li> ';
// irgendeinen rekursiven Aufruf zusammenbasteln
$this->BuildMenu($Item->GetItems());
// bla blub
}
[...]
return $htmlMenu;
}
}
MfG,
Sympatisant
Hi,
Nur mal so als Denkanstoss - kann man natuerlich beliebig variieren:
Danke, hat mir sehr geholfen!
Eine Frage, wenn ich ein Item hinzufüge mache ich das im Moment so:
$mymenu = new menu; # erst mal Menü erzeugen
$myitem = new menuItem; # Submenu anlegen
$myitem->url = 'index.html'; # Wert setzen
$mymenu->addItem($myitem); # hinzufügen
um jetzt einen neuen hinzuzufügen, muss ich also immer schreiben:
$myitem->url = 'index.html'; # Wert setzen
$mymenu->addItem($myitem); # hinzufügen
oder gibt es da irgendeine Kurzform á la $mymenu->addItem(menuItem(<url>, <andere variablen>, <.>));
?
Ok, ich kann mir ja einfach eine Funktion schreiben die das dann intern erledigt, ich denke das ist das einfachste..
Gruß
Salvete,
Ich wuerde die (wirklich) benoetigten Werte in den Kostruktr mit aufnehmen.
In etwa wie folgt:
// Ein Menu-Item
public class MenuItem
{
public __construct( $text, $url, $tooltip)
{
$this->Text = $text;
$this->Url = $url;
$this->ToolTip = $tooltip;
}
[..]
}
Dann kannst du das vereinfachen. Zum Beispiel so:
$menuItem = new MenuItem("link1", "http://www.google.de", "Google");
$mymenu->addItem($menuItem);
oder einzeilig
$mymenu->addItem( new MenuItem("link1", "http://www.google.de", "Google") );
MfG,
Sympatisant