針對 WordPress 大型網絡的後台加速方案

WordPress 多站點是一個很棒的工具,但它有其局限性和警告,特別是當你處理非常大的網絡時。在薇曉朵網站,我們使用此代碼段來阻止 “我的網站” 菜單查詢用戶所屬的網絡上的每個網站。

這對於小型網絡或只是少數博客/網站的用戶來說並不是那麼糟糕,但如果你有超級管理員,他們是大多數(如果不是全部)網站的成員,那麼你肯定會想要這個片段。

/**
 * Loading all sites menu for large multisite
 * is inefficient and bad news
 */
function large_network_remove_wp_admin_bar_my_sites_menu() {
    remove_action( 'admin_bar_menu', 'wp_admin_bar_my_sites_menu', 20 );
}
add_action( 'add_admin_bar_menus', 'large_network_remove_wp_admin_bar_my_sites_menu' );
 
/**
 * Let's replace that menu with one that has
 * links to the network dashboard instead.
 */
function large_network_replacement_my_sites_menu( $wp_admin_bar ) {
    if ( ! current_user_can( 'manage_network' ) ) {
        // bail.. no network menu for you!
        return;
    }
    
    $wp_admin_bar->add_menu( array(
        'id'    => 'prefix-my-sites',
        'title' => __( 'My Sites' ),
        'href'  => admin_url( 'my-sites.php' ),
    ));
 
    $wp_admin_bar->add_menu( array(
        'id'    => 'prefix-network-admin',
        'parent' => 'prefix-my-sites',
        'title' => __( 'Network Dashboard' ),
        'href'  => network_admin_url(),
    ));
 
    $wp_admin_bar->add_menu( array(
        'id'    => 'prefix-network-sites',
        'parent' => 'prefix-my-sites',
        'title' => __( 'Network Sites' ),
        'href'  => network_admin_url( 'sites.php' ),
    ));
 
    $wp_admin_bar->add_menu( array(
        'id'    => 'prefix-network-users',
        'parent' => 'prefix-my-sites',
        'title' => __( 'Network Users' ),
        'href'  => network_admin_url( 'users.php' ),
    ));
}
add_action( 'admin_bar_menu', 'large_network_replacement_my_sites_menu', 20 );

更新:當 WordPress 用戶登錄並且是許多站點的成員(例如數千個)時,仍然存在一些性能問題。我在 WordPress trac 上創建了一張新票,希望它有一些動力,但在那之前我提供了一個有用的片段,它有助於解決超級管理員成為數千個網站 “成員” 的問題。

/**
 * Remove all site capability keys when retrieving user meta
 * This prevents `get_blog_details` lookups for all the sites
 * a super admin is a member or admin
 *
 * @link  https://core.trac.wordpress.org/ticket/31746#comment:1 get_blogs_of_user() can be very slow when a user is a member of thousands of sites
 */
function large_network_skip_get_blogs_of_user_with_many_sites( $null, $object_id, $meta_key ) {
    global $wpdb;
 
    // Don't proceed if fetching a specific meta key, or the current user is not a super admin
    if ( $meta_key || ! is_super_admin() ) {
        return $null;
    }
 
    // Ok, then fetch all the user meta (remove this filter to do so)
    remove_filter( 'get_user_metadata', __FUNCTION__, 10, 4 );
    $keys = get_user_meta( $object_id );
    add_filter( 'get_user_metadata', __FUNCTION__, 10, 4 );
 
    // And loop through them
    foreach ( $keys as $key => $value ) {
        // Ignore non-capability meta keys
        if ( 'capabilities' !== substr( $key, -12 ) ) {
            continue;
        }
 
        // Ignore meta keys w/o the base_prefix
        if ( $wpdb->base_prefix && 0 !== strpos( $key, $wpdb->base_prefix ) ) {
            continue;
        }
 
        // Attempt to get the blog id from the string
        $blog_id = str_replace( array( $wpdb->base_prefix, '_capabilities' ), '', $key );
 
        // If it's not numeric, ignore this too
        if ( ! is_numeric( $blog_id ) ) {
            continue;
        }
 
        // Ok, let's black-list this capability meta from being sent back
        unset( $keys[ $key ] );
    }
 
    return $keys;
}
add_filter( 'get_user_metadata', 'large_network_skip_get_blogs_of_user_with_many_sites', 10, 3 );
文章沒看懂?代碼不會用?需要幫助您可以去論壇提問自助服務台