Immer wieder stoße ich bei WordPress auf ein paar Funktionen, die nicht optimal laufen. Beim Menü kommen hier ein paar verschiedene zusammen.
Ich finde das Handling sehr in Ordnung, obwohl es bei sehr großen Menüs durchaus ein wenig lästig werden kann. Das ist eigentlich der Hauptkritikpunkt an der WordPress Version davon.
Was mir schon in vielen Systemen passiert ist, ist dass das Ausgeben von Menüs sehr rechen- und damit zeitintensiv ist, weshalb sich hier anbietet, die Menüs zu cachen.
Ich habe diese Variante auf wordpress.stackexchange.com veröffentlicht, und bringe sie hiermit auf meinen Blog.
Hier werden einige coole WordPress-Features verwendet: das Action-Hook Modell und Transienten.
Als erstes zur Ausgabe des Menüs. Dies erledigt von nun an folgende Funktion:
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 |
function get_cached_menu( $menuargs ) { // determine if menu is called via menu-slug or theme_location if ( !isset( $menuargs['menu'] ) ) { $theme_locations = get_nav_menu_locations(); $nav_menu_selected_id = $theme_locations[$menuargs['theme_location']]; $termslug = get_term_by( 'id', $nav_menu_selected_id, 'nav_menu' ); $transient = 'menu_' . $termslug->slug . '_transient'; } else { $transient = 'menu_' . $menuargs['menu'] . '_transient'; } if ( !get_transient( $transient ) ) { // check if the menu is already cached $menuargs['echo'] = '0'; // set the output to return $this_menu = wp_nav_menu( $menuargs ); // build the menu with the given $menuargs echo $this_menu; // output the menu for this run set_transient( $transient, $this_menu ); // set the transient, where the build HTML is saved } else { echo get_transient( $transient ); // just output the cached version } } |
$menuargs
ist ein ganz normales Array
, das die selben Werte beinhalten kann wie $args
für wp_nav_menu()
. Im ersten Schritt wird überprüft, ob das Menü nach der Position im Theme, oder ob ein anderes Menü direkt aufgerufen wird. Aus dem Slug des Menüs ergibt sich der Name für den Transienten.
Im zweite Schritt wird überprüft, ob der Transient in der Datenbank vorhanden ist. Falls nicht, wird das gewöhnliche wp_nav_menu()
mit allen übergebenen Optionen aufgerufen, allerdings mit unterdrückter Ausgabe. Dies wird benötigt, um das fertige Menü als Transient abspeichern zu können. Falls er schon vorhanden ist, wird einfach nur eine Datenbankquery abgesetzt, um den Inhalt dieses Feldes auszugeben, und voilá – das passt soweit.
Das gute an Menüs auf einer Homepage ist, dass sie nicht oft erneuert werden/werden müssen/werden sollen.
Mit der obigen Funktion wird das Menü abgespeichert, aber wenn es nun erneuert wird, muss dieser Cache natürlich wieder gelöscht werden. Aus diesem Grund lasse ich beim Speichern des Menüs folgende Funktion per ActionHook ausführen:
1 2 3 4 5 6 7 8 9 10 |
add_action('wp_update_nav_menu', 'f711_delete_menu_transients'); function f711_delete_menu_transients($nav_menu_selected_id) { $termslug = get_term_by( 'id', $nav_menu_selected_id, 'nav_menu' ); $transient = 'menu_' . $termslug->slug . '_transient'; delete_transient( $transient ); } |
Die (integer)ID des Menüs wird beim Speichern an diese Funktion übergeben. Hieraus wird dann der Name des dazugehörigen Transienten gebildet (Über den kleinen Umweg der Taxonomie), und der zugeordnete Cache geleert.
Hiermit kann ich bei der WordPress Performance sehr viel Rechenleistung einsparen, besonders bei großen Seiten, und das ganze benötigt nicht mehr als ein paar Zeilen Code für die functions.php
.
Speed-Metal on!
Hallo, Endlich mal eine gute Seite auf Deutsch 🙂
Was ich mich hierbei frage ist, da ich mich mit Cache Funktionen noch nicht richtig beschäftigt habe, ob es nicht besser wäre den Namen zu verschlüsseln und zu ’sanitize‘, wie in etwa:
$transitions_name = ‚menu_‘ . md5( sanitize_key( $termslug->slug ) . ‚_transient‘ );
So habe ich es bis jetzt z.B. im Quellcode von Woocommerce gefunden beim zusammenspiel der get_posts und der get_objects_in_term funktion.
Oder ist dies unnötig, oder lediglich für bestimmte Datentypen wichtig, wie Passwörter oder Benutzerdaten?
Servus Jamal, sorry für die späte Antwort.
ich würde hier den Termslug nicht verschlüsseln – sanitizing schadet natürlich nie, allerdings ist der Slug sowieso schon urlcodiert.
Der Slug ist auch nicht geheim – der steht öfters im Quellcode und in den URLs, und für den User ist die Datenbank durch diesen Eingriff nicht verfügbar.
Hoffe das hilft dir soweit weiter 🙂