Nicht nur, dass sich damit das Hauptmenü selbst aufbauen lässt, und ich meine nicht nur die Reihenfolge der einzelnen Seiten, sondern die gesamte Menüstruktur. Also auch welche Seite nicht angezeigt werden sollen und so weiter. Nein, je nach Theme hat man so mehrere mögliche Positionen um ein Menü unter zu bringen. Auf dieser Seite sind es zum Beispiel drei Menüs. Auch über ein Sidebarwidget kann man eigene Menüs in der Sidebar unterbringen. Ihr seht schon, viel Potential!

Natürlich lässt sich auch die Seite damit wunderbar strukturieren. Wie folgendes Beispiel zeigen soll. Gegeben sei eine Seite die in mehrere Bereiche aufgeteilt werden soll. Jeder Bereich hat dabei seine eigene Navigation. Dies betrifft auch die Unterseiten dieses Bereiches. Also braucht erst mal jeder Bereich in WordPress selbst eine Navigation. Diese sind schnell erstellt im Backend und haben auch schnell eindeutige Namen bekommen – Bereich 1, Bereich 2 und Bereich 3. Kann jeder was mit anfangen.

Nun zu der Herausforderung, die Unterseiten eines jeden Bereiches mit der entsprechenden Navigation zu versehen. Ist ganz einfach, wenn man erst mal die Custom Fields ebenfalls für sich entdeckt hat. Das sind diese kleinen lustigen Felder die man einer Seite zuordnen und der Seite somit noch ein paar Attribute mitgeben kann. Diese „missbrauchen“ wir nun für das Menü.

Man erzeugt also kein neues Custom Field (Benutzerdefiniertes Feld) mit dem Namen page_menu und als Wert wird der Name oder der „Slug“ des gewünschten Menüs eingetragen. Dann  nutzt man Google und sucht sich eine Funktion die das ausliest und das entsprechende Menü läd. Wer nun nicht Google nutzen möchte, dem kann ich diese Seite von Frank Bültge ans Herz legen, wo er genau diese Funktion in Zusammenhang mit benutzerdefinierten Feldern beschreibt. Klasse Sache. Natürlich ist es jedes Mal etwas viel Arbeit, erst das Custom Field erstellen, dann muss man sich auch noch an den Namen des Menüs erinnern. Das muss doch auch einfacher gehen.

Custom Menu Meta BoxJA! Geht es. Denn das schöne an WordPress ist, man kann es fast beliebig erweitern. Und so habe ich mir die Funktion von Frank Bültge vorgenommen und etwas erweitert. Herausgekommen ist dabei ein Meta-Widget. Das ist so ein lustiges Ding, was ihr euch bei Editieren einer Seite im Backend mit anzeigen lassen könnt. In diesem kleinen Widget kann man dann in aller Ruhe das gewünschte Menü auswählen. Klasse oder?

Nimmt einem also ne ganze Menge Arbeit ab das kleine Helferlein.

Ok, der Code dafür ist natürlich etwas umfangreicher als der den Herr Bültge veröffentlicht hat und ich möchte euch diesen nicht vorenthalten. Hier also der Umbau:

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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<?php
/**
 * Erstellt eine Meta Box um einer Seite ein eigenes Menü mit zu geben.
 * Die Menüs müssen unter Design -> Menü definiert sein.
 *
 * @author H.-Peter Pfeufer
 */

if(!class_exists('Page_Menu_Meta_Box')) {
    class Page_Menu_Meta_Box {
        private $textdomain = 'meine-textdomain';   // Textdomain für die Übersetzung
        private $posttype = 'page';                 // Posttype (hier page für Seiten)
        private $metaname = 'page_menu';            // Name des Custom Fields
        private $metaboxID = 'page_menu';           // ID der Metabox
        private $noncename = 'page_menu';           // Name des Nonce (etwas für die Sicherheit
        private $defaultmenu = 'default';           // "Slug" des Standardmenüs
        private $userright = 'edit_page';           // Nutzerrechte die benötigt werden
        private $selectname = 'page-menu';          // Name des Selectferldes

        /**
         * Constructor (old style)
         *
         * @uses __construct
         */

        function Page_Menu_Meta_Box() {
            self::__construct();
        } // END function Page_Menu_Meta_Box()

        /**
         * Constructor
         */

        function __construct() {
            // Backend
            if(is_admin()) {
                add_action('add_meta_boxes', array(
                    &$this,
                    '_add_meta_box'
                ));

                add_action('save_post', array(
                    &$this,
                    '_save_page_menu'
                ));
            } // END if(is_admin())

            // Frontend
            if(!is_admin()) {
                add_filter('wp_nav_menu_args', array(
                    &$this,
                    '_menu_per_page'
                ));
            } // END if(!is_admin())
        } // END function __construct()

        /**
         * Metabox am System anmelden
         */

        function _add_meta_box() {
            add_meta_box($this->metaboxID, __('Select the menu for this page', $this->textdomain), array(
                &$this,
                'the_meta_box'
            ), $this->posttype, 'normal', 'high');
        } // END function _add_meta_box()

        /**
         * Metabox erstellen
         */

        function the_meta_box() {
            global $post;

            // Menüs abholen
            $menues = wp_get_nav_menus();

            if(!empty($menues) && count($menues) != 0) {
                // Use nonce for verification
                wp_nonce_field(plugin_basename( __FILE__ ), $this->noncename);

                // Ist bereits ein Menü gewählt?
                $menuslug = get_post_meta($post->ID, $this->metaname, true);

                // Setting the defaultmenu
                if(empty($menuslug)) {
                    $menuslug = $this->defaultmenu;
                } // END if(empty($menu_name))

                echo sprintf('<p>%1$s</p>', __('Please select the menu which should be displayed on this page.', $this->textdomain));
                echo '<select name="' . $this->selectname . '">';

                foreach($menues as $menu) {
                    if(!empty($menuslug)) {
                        $selected = '';

                        if($menuslug == $menu->slug) {
                            $selected = ' selected="selected"';
                        } // END if($menu_name == $menu->slug)
                    } // END if(!empty($menu_name))

                    echo '<option value="' . $menu->slug . '"' . $selected . '>' . $menu->name . '</option>';
                } // END foreach($menues as $menu)

                echo '</select>';
            } // END if(!empty($menues) && count($menues) != 0)
        } // END function the_meta_box()

        /**
         * Daten speichern
         *
         * @param int $post_id
         */

        function _save_page_menu($post_id) {
            // Erst mal schauen wir, ob der Nutzer das überhaupt darf
            if(!current_user_can($this->userright, $post_id)) {
                return;
            }

            // Dann prüfen wir die Nonces
            if(!isset($_REQUEST[$this->noncename]) || !wp_verify_nonce($_REQUEST[$this->noncename], plugin_basename(__FILE__))) {
                return;
            } // END if(!isset($_REQUEST['vokabel_page_menu']) || !wp_verify_nonce($_REQUEST['vokabel_page_menu'], plugin_basename(__FILE__)))

            // und nun wird der ganze Hokuspokus gespeichert
            $post_id = $_REQUEST['post_ID'];

            // Metainformationen hinzufügen oder aktualisieren
            add_post_meta($post_id, $this->metaname, $_REQUEST[$this->selectname], true) or update_post_meta($post_id, $this->metaname, $_REQUEST[$this->selectname]);
        } // END function _save_page_menu($post_id)

        /**
         * Menü im Frontend anzeigen
         *
         * @param array $args
         * @return Ambigous <mixed, string, multitype:, boolean, array, string>
         */

        function _menu_per_page($args = '') {
            if(is_page()) {
                global $post;

                $menuslug = get_post_meta($post->ID, $this->metaname, true);

                if(!empty($menuslug) && is_nav_menu($menuslug)) {
                    $args['menu'] = $menuslug;
                } // END if(!empty($menu_name) && is_nav_menu($menu_name))
            } // END if(is_page())

            return $args;
        } // END function _menu_per_page($args = '')
    } // END class Page_Menu_Meta_Box

    // Klasse starten
    new Page_Menu_Meta_Box();
} // END if(!class_exists('Page_Menu_Meta_Box'))

Viel Spaß damit :-)

Artikel / Seite weiterempfehlen

13 Meinungen zu “Spaß mit den Custom Menues von WordPress

  1. ich muss das Kommentar-Feld benutzen, denn alle Links im oberen Teil der Seite. auch der Link zu Kontakt etc. wird von feedly gefressen und als fehlerhaft in feedly angezeigt, statt den Seiteninhalt zu laden.

    Was ist da los? Ich hätte gerne ein paar Seiten mehr gelesen hier aber es gelingt mir nicht …

  2. H. Peter Pfeufer, echt genial!..vor allem wenn man bedenkt wieviele Plug Ins das nicht hinkriegen.
    Ihr Script hat mein Dasein verschönert.. Danke dafür. Ich hab versucht das so zu verändern das statt einem anderen Hauptmenü ein zusätzlicher horizontaler sub-header-menue unter den jeweiligen Mainmenü Items auf der Filmakademie Webseite erscheinen möge. – Ich bekomme das aber nicht hin. Wo könnte man die Menue position in der Metabox hinzufügen oder ein div sub-header-menue in der Ausgabe bestimmen. Ich wär für Hilfe sehr dankbar auch gegen Entgelt.

  3. Wie benutze ich dieses Widget? Also ich habe es bereits über die functions.php eingebunden, aber wie komme ich nun auf den Unterseiten an das Menü. Also wie kann ich das Menü tatsächlich ausgeben lassen?

    Gruß und danke schon mal für die Antwort.

  4. Hallo Peter,

    erst mal super vielen Dank für das ausführliche Tutorial, das Funktioniert tatsächlich exakt so wie Du es beschrieben hast und das habe ich echt dringend gebraucht.
    Jetzt habe ich noch ein Problem, was ich noch nicht lösen konnte.
    ich verwende ein Theme mit einem Haupt- und einen Top-Menu
    Durch den Aufruf bzw. Filtern des „Custom Field“ werden bei mir immer beide Menüs mit dem „neuen Menu“ geladen. Scheinbar werden beide Menüs mit der gleichen Funktion „has_nav_menu“ geladen.
    Sinnvoll wäre es wenn Sich das Topmenü nicht verändern würde, wenn ich das Hauptmenü auswähle.
    hier mal ein Auszug aus meiner „header.php“ in der ich den Aufruf der Menüs gesehen habe.

    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
    <?php if( ! get_option(RT_THEMESLUG.'_hide_top_bar') ):?>
        <!-- top bar -->
        <section id="top_bar" class="clearfix">
            <div class="top_bar_container">    


                        <ul id="top_navigation" class="top_links">

                            <!--  top links -->
                            <?php if ( has_nav_menu( 'rt-theme-top-navigation' ) ): // check if user created a custom menu and assinged to the rt-theme's location ?>
                                <?php  
                                    //call the top menu          
                                    $topmenuVars = array(
                                        'menu_id'         => "",
                                        'menu_class'      => "top_links",
                                        'container'       => '',
                                        'echo'            => true,
                                        'depth'           => 1,
                                        'theme_location'  => 'rt-theme-top-navigation',
                                        'items_wrap'      => '%3$s',
                                    );
                                   
                                    wp_nav_menu($topmenuVars);
                                ?>
                            <?php else:?>
                                <?php    

                                    //call the top menu          
                                    $topmenuVars = array(
                                        'menu'            => 'RT Theme Top Navigation Menu',  
                                        'menu_id'         => "top_navigation",
                                        'menu_class'      => "top_links",
                                        'container'       => '',
                                        'echo'            => true,
                                        'depth'           => 1,
                                        'theme_location'  => 'rt-theme-top-navigation',
                                        'items_wrap'      => '%3$s',
                                    );

                                    wp_nav_menu($topmenuVars);
                                ?>
                                <!-- / end ul .top_links -->
                            <?php endif;?>

    hast Du eine Idee, wie ich in der Funktions.php nun festlegen kann, das das Top-Menü nicht verändert werden soll ?

    vielen Dank schon mal für eine Meldung

    • Die Menüaufteilung sieht etwas eigenwillig aus muss ich zugeben.

      Aber nicht desto trotz ist diese kleine Funktion für Seiten mit nur einem Menü gedacht, bzw Seiten wo dies auch nach dem WordPress Standard erledigt wird, was hier nicht so ganz der Fall ist. Das Theme scheint bei Dir die WordPress eigene Menüerkennung irgendwie zu umgehen und was eigenes zu basteln. Sieht zumindest danach aus auf den ersten Blick.

  5. Hallo,
    ein sehr interessanter Artikel. Ich bin WordPress-Neuling und habe eigentlich wenig PHP- und HTML-Kenntnisse – deshalb ist mir das mit dem Code noch „etwas zu hoch“.

    Seit einiger Zeit beschäftige ich mich damit eine Kommunal-Seite mit „verzweigter“ Menüstruktur aufzubauen. Das heißt: eine Hauptnavigation die ca. fünf bis sechs Menüpunkte mit unterschiedlichen Rubriken/Kategorien im Kopfbereich der Seite enthält.
    Jede dieser Rubriken soll ca. zehn bis zwanzig Untermenüpunkte erhalten, welche dann jeweils auf die entsprechende Seite verweisen. Diese Untermenüs möchte ich gerne jeweils separat im linken oder rechten mittleren Bereich der Seite permament angezeigt haben, sobald man oben einen der Rubrikpunkte anklickt und nur solange bis ein anderer Punkt ausgewählt wird. Quasi eine |‾ L-Navigation. Ein Pulldown-Menü aus der Hauptnavigation heraus möchte ich vermeiden, weil ich denke dass wird schnell unübersichtlich. Ich nutze das Theme „Graphene“. Über das Widget „Individuelle Menü“ habe ich die Zuordnung der Untermenüs versucht und mir diese entprechend der Rubriken des Hauptmenüs erstellt. Es werden aber immer alle Unter-Menüs angezeigt. Man hat keine Möglickeit, das jeweils benötigte auszuwählen.

    Habe ich was übersehen oder geht das nicht? Ich finde keine Möglichkeit hier das jeweilige „Individuelle Menü“ auszuwählen.

    In HTML habe ich das früher schon mal über Frames realisiert. Aber diese Seite soll datenbankgestützt aufgebaut werden (… sie soll später von verschiedenen Personen – je nach Rubrik – gepflegt werden), weshalb dies nicht in Frage kommt. Außerdem läuft meine derzeitige Dreamweaver-Version nicht mehr unter dem neuesten OSX ich müsste upgraden und auf das Adobe-CC-Abo-Modell habe ich keine Lust.

    In Joomla gehts auch – das erscheint mir aber zu komplex für meine „Mitstreiter“ die später Texte einstellen sollen.

    Gibt es hier eine Lösung über ein Plug-In?

Schreibe einen Kommentar

Ihre Email-Adresse wird nicht veröffentlicht. Pflichtfelder sind durch * markiert.

Sie können folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>