wordpress自定义菜单功能对于网站的导航菜单管理非常方便,但该功能的执行效率比较低下,当自定义菜单比较复杂的情况下会产生过多的SQL查询,影响博客的速度。针对这个问题,我爱水煮鱼博客的博主通过pre_wp_nav_menu
filter 接口对生成的自定义菜单进行缓存,大大提高页面的效率。
适用于WordPress 3.9以上版本:
把下面的代码添加到当前主题functions.php文件的第一行<?php 下面即可:
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 | //给 wp_nav_menu 加上对象缓存,加快效率 add_filter( 'pre_wp_nav_menu', 'wpjam_get_nav_menu_cache', 10, 2 ); function wpjam_get_nav_menu_cache( $nav_menu, $args ) { $cache_key = wpjam_get_nav_menu_cache_key($args); $cached_menu = get_transient( $cache_key ); if ( ! empty( $cached_menu ) ) return $cached_menu; return $nav_menu; } add_filter( 'wp_nav_menu', 'wpjam_set_nav_menu_cache', 10, 2 ); function wpjam_set_nav_menu_cache( $nav_menu, $args ) { $cache_key = wpjam_get_nav_menu_cache_key($args); set_transient( $cache_key, $nav_menu, 86400 ); return $nav_menu; } function wpjam_get_nav_menu_cache_key($args){ $timestamp = get_transient('nav-menu-cache-timestamp'); if($time === false){ $timestamp = time(); set_transient( 'nav-menu-cache-timestamp', $time, 86400 ); } return apply_filters( 'nav_menu_cache_key' , 'nav-menu-' . md5( serialize( $args ).serialize(get_queried_object()) ) . $timestamp ); } // 更新菜单,清理缓存 add_action( 'wp_update_nav_menu', 'wpjam_delete_nav_menu_cache' ); function wpjam_delete_nav_menu_cache( $menu_id, $menu_data){ set_transient( 'nav-menu-cache-timestamp', time(), 86400 ); } |
附:WordPress 3.9以下版本:
1、把下面的代码添加到当前主题functions.php文件的第一行<?php
下面:
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 | //给 wp_nav_menu 加上对象缓存,加快效率 function wpjam_nav_menu( $args = array() ) { static $menu_id_slugs = array(); $defaults = array( 'menu' => '', 'container' => 'div', 'container_class' => '', 'container_id' => '', 'menu_class' => 'menu', 'menu_id' => '', 'echo' => true, 'fallback_cb' => 'wp_page_menu', 'before' => '', 'after' => '', 'link_before' => '', 'link_after' => '', 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>', 'depth' => 0, 'walker' => '', 'theme_location' => '' ); $args = wp_parse_args( $args, $defaults ); $args = apply_filters( 'wp_nav_menu_args', $args ); $args = (object) $args; // Get the nav menu based on the requested menu $menu = wp_get_nav_menu_object( $args->menu ); // Get the nav menu based on the theme_location if ( ! $menu && $args->theme_location && ( $locations = get_nav_menu_locations() ) && isset( $locations[ $args->theme_location ] ) ) $menu = wp_get_nav_menu_object( $locations[ $args->theme_location ] ); // get the first menu that has items if we still can't find a menu if ( ! $menu && !$args->theme_location ) { $menus = wp_get_nav_menus(); foreach ( $menus as $menu_maybe ) { if ( $menu_items = wpjam_get_nav_menu_items( $menu_maybe->term_id, array( 'update_post_term_cache' => false ) ) ) { $menu = $menu_maybe; break; } } } // If the menu exists, get its items. if ( $menu && ! is_wp_error($menu) && !isset($menu_items) ) $menu_items = wpjam_get_nav_menu_items( $menu->term_id, array( 'update_post_term_cache' => false ) ); /* * If no menu was found: * - Fallback (if one was specified), or bail. * * If no menu items were found: * - Fallback, but only if no theme location was specified. * - Otherwise, bail. */ if ( ( !$menu || is_wp_error($menu) || ( isset($menu_items) && empty($menu_items) && !$args->theme_location ) ) && $args->fallback_cb && is_callable( $args->fallback_cb ) ) return call_user_func( $args->fallback_cb, (array) $args ); if ( !$menu || is_wp_error( $menu ) || empty( $menu_items ) ) return false; $nav_menu = $items = ''; $show_container = false; if ( $args->container ) { $allowed_tags = apply_filters( 'wp_nav_menu_container_allowedtags', array( 'div', 'nav' ) ); if ( in_array( $args->container, $allowed_tags ) ) { $show_container = true; $class = $args->container_class ? ' class="' . esc_attr( $args->container_class ) . '"' : ' class="menu-'. $menu->slug .'-container"'; $id = $args->container_id ? ' id="' . esc_attr( $args->container_id ) . '"' : ''; $nav_menu .= '<'. $args->container . $id . $class . '>'; } } // Set up the $menu_item variables _wp_menu_item_classes_by_context( $menu_items ); $sorted_menu_items = array(); foreach ( (array) $menu_items as $key => $menu_item ) $sorted_menu_items[$menu_item->menu_order] = $menu_item; unset($menu_items); $sorted_menu_items = apply_filters( 'wp_nav_menu_objects', $sorted_menu_items, $args ); $items .= walk_nav_menu_tree( $sorted_menu_items, $args->depth, $args ); unset($sorted_menu_items); // Attributes if ( ! empty( $args->menu_id ) ) { $wrap_id = $args->menu_id; } else { $wrap_id = 'menu-' . $menu->slug; while ( in_array( $wrap_id, $menu_id_slugs ) ) { if ( preg_match( '#-(\d+)$#', $wrap_id, $matches ) ) $wrap_id = preg_replace('#-(\d+)$#', '-' . ++$matches[1], $wrap_id ); else $wrap_id = $wrap_id . '-1'; } } $menu_id_slugs[] = $wrap_id; $wrap_class = $args->menu_class ? $args->menu_class : ''; // Allow plugins to hook into the menu to add their own <li>'s $items = apply_filters( 'wp_nav_menu_items', $items, $args ); $items = apply_filters( "wp_nav_menu_{$menu->slug}_items", $items, $args ); $nav_menu .= sprintf( $args->items_wrap, esc_attr( $wrap_id ), esc_attr( $wrap_class ), $items ); unset( $items ); if ( $show_container ) $nav_menu .= '</' . $args->container . '>'; $nav_menu = apply_filters( 'wp_nav_menu', $nav_menu, $args ); if ( $args->echo ) echo $nav_menu; else return $nav_menu; } function wpjam_get_nav_menu_items( $menu, $args = array() ) { $menu = wp_get_nav_menu_object( $menu ); $menu_items = get_transient('wpjam_nav_menu_'.$menu->term_id); if($menu_items === false){ $menu_items = wp_get_nav_menu_items( $menu->term_id, $args ); set_transient('wpjam_nav_menu_'.$menu->term_id, $menu_items, 3600); } return $menu_items; } //后台更新自定义菜单的时候,更新缓存 add_action( 'wp_update_nav_menu', 'wpjam_update_nav_menu' ); function wpjam_update_nav_menu( $menu_id = null, $menu_data = null ) { delete_transient('wpjam_nav_menu_'.$menu_id); } |
2、使用wpjam_nav_menu
函数替代原来的wp_nav_menu
函数调用。
代码转自我爱水煮鱼博客