FSE – dynamischen Menüblock mit Werten aus einem Custom Field bestücken

805 0835
Foto von Gabriele Lässer

In einem Projekt kommt es immer mal wieder vor, dass eine Landingpage zu einem bestimmten Thema angelegt wird. Die Menüleiste besteht aus Ankerlinks, und je nach Thema unterscheiden die sich. Jede Landingpage hat also ihr eigenes Menü, bräuchte also potentiell ein eigenes Template mit entsprechendem Template Part (Header) und eigenem Menü.

Die Idee war nun, für alle Landingspages dasselbe Template vorzusehen, und das Menü dynamisch zu bestücken. In einem klassichen Theme mit PHP-Templates wäre das ein Kinderspiel gewesen. Schwer vorstellbar, dass es in FSE-Themes keinen Weg dahin gibt.

Für die Umsetzung habe ich das (kostenlose) Plugin Metabox verwendet (ACF funktionierte nicht, für die Menüs brauchte es ein Repeater Feld, ging der Sache nicht intensiv nach, sondern testete gleich mit Metabox weiter) , um die Custom Fields zu verwalten. Zudem gehe ich (in jedem Beitrag) davon aus, dass die gerade aktuelle WordPress-Version verwendet wird (in diesem Fall 6.5.2).

Im (Child-)Theme nun folgende Schritte durchführen:

Das page.html Template (unter templates) kopieren, und umbenennen, zum Beispiel landing-page.html. Es ist nicht zwingend erforderlich, jedoch sinnvoll, das neue Template in der theme.json unter customTemplates zu registrieren.

	"customTemplates": [
...
		{
			"name": "landing-page",
			"title": "Landing Page",
			"postTypes": [ "page" ]
		}
	]

Den header.html Template Part (unter parts) kopieren, und die Kopie header-landing.html nennen. Es muss nicht zwingend in den templateParts registiert werden, schadet allerdings auch nicht, es zu tun.

Die dritte erforderliche Datei ist eine PHP-Datei, kommt in das Verzeichnis patterns und heißt in unserem fall „hidden-dynamic-navigation.php“. Der Teil „hidden“ verhindert, dass das Pattern an beliebiger Stelle eingefügt werden kann. Es soll jedoch einfach nur Bestandteil unseres Header-Template-Parts sein.

Damit das Pattern verwendet werden kann, benötigt es einen Namen (bei Patterns ist der Name den es bekommt entscheidend, nicht der Name der Datei). Die hidden-dynamic-navigation beginnt z.B. so:

<?php

/**
 * Title: Dynamic Navigation
 * Slug: mytheme/dynamic-navigation
 * Inserter: no
 *
 * @package mytheme
 * @since 1.0.0
 */
?>

Wichtig ist, auch immer den Slug des Themes zu verwenden. An der Position im Template-Part „header-landing.html“, an der vorgesehen ist die Hauptnavigation unterzubringen, nun das Pattern aufrufen, und zwar so:

<!-- wp:pattern {"slug":"mytheme/dynamic-navigation"} /-->

Ok, es ist an der Zeit sich um die Customfields der Landingpages zu kümmern. Vorgesehen ist, dass die Landingspages Ankerlinks bekommen (günstigerweise die ID der Überschrift der jeweiligen Sektion, die angesteuert werden soll). Diese müssen auf jeden Fall vergeben werden (wobei man natürlich auch den Inhalt nach z.B. h3-IDs durchsuchen und daraus dynamisch eine Navigation extrahieren könnte, allerdings wären die Labels dann die Überschriften und am Ende vielleicht zu lang…).

add_filter('rwmb_meta_boxes', 'mytheme_landing_page_menu');

function mytheme_landing_page_menu($meta_boxes)
{
    $prefix = 'lp_';

    $meta_boxes[] = [
        'title'         => __('Landing Pages Menu', 'mytheme'),
        'id'            => 'landing_pages_menu',
        'post_types'    => ['page'],
        'fields'        => [
            [
                'name'        => __('Ankerlinks', 'mytheme'),
                'id'          => $prefix . 'landing_ankerlinks',
                'type'        => 'group',
                'collapsible' => true,
                'clone'       => true,
                'sort_clone'  => true,
                'fields'      => [
                    [
                        'name'       => __('Ankerlink', 'mytheme'),
                        'id'         => $prefix . 'ankerlink',
                        'type'       => 'text',
                        'pattern'   => '^[a-z0-9-]+$',
                        'limit_type' => 'character',
                    ],
                    [
                        'name'       => __('Ankerlinklabel', 'mytheme'),
                        'id'         => $prefix . 'ankerlinklabel',
                        'type'       => 'text',
                        'limit_type' => 'character',
                    ],
                ],
            ]
        ],
    ];

    return $meta_boxes;
}

Das „pattern“ im Ankerlink-Feld legt fest, dass nur Kleinbuchstaben, Ziffern und Bindestriche erlaubt sind, wie in Clean-URLs von WordPress selbst auch.

Die Feldgruppe ist klonbar, d.h. es können so viele Ankerlinks und Labels angegeben werden wie man braucht (resp. im Content tatsächlich vorkommen). Nochmal zurück zur hidden-dynamic-navigation.php und dem noch fehlenden Code für die Navigation.

<?php 
global $post;
$page_id = $post->ID; 
$prefix = 'lp_';
$lplinks = get_post_meta($page_id, $prefix . 'landing_ankerlinks', true);
if (!$lplinks) {
    return;
}
$headernavblock = '<!-- wp:navigation {"textColor":"contrast","icon":"menu","className":"Main Navigation","isResponsive":true,"style":{"typography":{"textTransform":"uppercase","lineHeight":"2.8"}}} -->';
if ($lplinks) {
    foreach ($lplinks as $link) {
        $headernavblock .= '<!-- wp:navigation-link {"label":"' . $link[$prefix . 'ankerlinklabel'] . '","url":"#' . esc_attr($link[$prefix . 'ankerlink']) . '"} /-->';
    }
}
$headernavblock .= '<!-- /wp:navigation -->';
echo do_blocks($headernavblock);

Dieser Teil

<!-- wp:navigation {"textColor":"contrast","icon":"menu","className":"Main Navigation","isResponsive":true,"style":{"typography":{"textTransform":"uppercase","lineHeight":"2.8"}}} -->

orientiert sich daran, wie die Navigation in anderen Seiten definiert ist. Ich hab‘ sie aus der Codeansicht des Site-Headers kopiert und übernommen.

Bitte Kommentarfunktion nicht für Supportanfragen nutzen. Dem kann hier nicht entsprochen werden. Die Angabe einer E-Mail-Adresse und eines Namens ist nicht erforderlich. Einen (Spitz)-Namen zu nennen wäre aber doch nett.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Hinweis: Sowohl angegebener Name als auch E-Mail-Adresse (beides ist optional, dafür werden alle Kommentare vor Veröffentlichung geprüft) werden dauerhaft gespeichert. Du kannst jeder Zeit die Löschung Deiner Daten oder / und Kommentare einfordern, direkt über dieses Formular (wird nicht veröffentlicht, und im Anschluss gelöscht), und ich werde das umgehend erledigen. – Mit hinterlassenen Kommentaren hinterlegte IP-Adressen werden nach zwei Monaten automatisch gelöscht

publicly queryable