wordpress缓存自定义菜单优化博客速度

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函数调用。

代码转自我爱水煮鱼博客

发表留言