Global page navigation accross WordPress MU blogs

Here’s the scenario. You have a WordPress MU site with multiple blogs, but for whatever reason, you want every blog to have the same main navigation and pages. Your main site/blog hosts all of your pages. So how do you go about creating a WordPress MU Theme that will use the navigation and pages from your main site/blog accross all of your blogs? Well, I’m here to tell you how I did it.

The WordPress Codex has a function called ‘wp_list_pages.’ What I wanted to do is create a new function called ‘wp_list_main_pages.’ So I simply searched my WordPress install and copied the ‘get_pages’ and ‘wp_list_pages’ functions and pasted them into my theme’s ‘functions.php’ file. From here I made a few edits to these functions. To start with, I renamed them ‘wp_list_main_pages’ and ‘get_main_pages.’

Below is the final code I’m using to display the main navigation accross blogs. I made notes in bold to help. Hope this is helpful to you Googling coders. 🙂

// You can use this function instead of 'wp_list_pages' in your theme
function wp_list_main_pages($args = '') {
	$defaults = array(
		'depth' => 0, 'show_date' => '',
		'date_format' => get_option('date_format'),
		'child_of' => 0, 'exclude' => '',
		'title_li' => __('Pages'), 'echo' => 1,
		'authors' => '', 'sort_column' => 'menu_order, post_title'
	);

	$r = wp_parse_args( $args, $defaults );
	extract( $r, EXTR_SKIP );

	$output = '';
	$current_page = 0;

	// sanitize, mostly to keep spaces out
	$r['exclude'] = preg_replace('[^0-9,]', '', $r['exclude']);

	// Allow plugins to filter an array of excluded pages
	$r['exclude'] = implode(',', apply_filters('wp_list_pages_excludes', explode(',', $r['exclude'])));

	// Query pages.
	$r['hierarchical'] = 0;
	// Right here we call our new 'get_main_pages' function
	$pages = get_main_pages($r);

	if ( !empty($pages) ) {
		if ( $r['title_li'] )
			$output .= '<li class="pagenav">' . $r['title_li'] . '<ul>';

		global $wp_query;
		if ( is_page() || $wp_query->is_posts_page )
			$current_page = $wp_query->get_queried_object_id();
		$output .= walk_page_tree($pages, $r['depth'], $current_page, $r);

		if ( $r['title_li'] )
			$output .= '</ul></li>';
	}

	$output = apply_filters('wp_list_pages', $output);

	// This line is sloppy and needs improvement.
	// You have to remove the name of the blog your currently on from you global navigation.
	// I'm doing this the simplest but least scalable way here.
	$output = str_replace("pressroom/", "", $output);

	if ( $r['echo'] )
		echo $output;
	else
		return $output;
}

// This is essentially a private function
function &get_main_pages($args = '') {
	global $wpdb;

	// This is the magic line.
	// Now when the SQL runs to pull your navigation pages, it'll use your main blogs ID.
	$wpdb->set_blog_id(1);

	// Notice here I call the original get_pages function and return the results
	$pages = get_pages($args);
	return $pages;
}

20 thoughts on “Global page navigation accross WordPress MU blogs

  1. btw can I limint which pages are shown like normal?

    <?php wp_list_pages(‘include=7,13,26,35&title_li=’ . __(‘Pages’) . ” ); ?>

    would be

    <?php wp_list_main_pages(‘include=7,13,26,35&title_li=’ . __(‘Pages’) . ” ); ?>

    ???
    I tried that and the menu didn’t show up at all.

    Next step if to get them horizontal.

  2. ok I got all that in order now, but here is another brain twister for ya, and if you can make it happen I got $30 for ya. Now that each blog is pulling linking structure of the main blog, and we have those links pull the data for those links from the main blog as well. Example, I have 20 blogs all in the same niche, and I wish them all to use the same pages from one master blog, so if I want to make a change, I can do it on that one instead of all 20.

    What ya think? Would really enjoy hearing back from you.

  3. 101ramennoodlerecipes.com is an example and if you hit the recipes link you will see a list, all the sites on the rigth hand side are WP.

    Ok, so as you look through the sites, you will see the all look the same, have the same links and even pages.

    What I would like, is for each blog, no matter what URL
    101ramennoodlerecipes.com/recipes
    or
    3beansaladrecipe.com/recipes

    that page should pull from one DB table, so if I change it on 101ramennoodlerecipes it will change on
    3beansaladrecipe.

    I know this is not something the average person running a blog community would want, but I’m not running a blog community 🙂

  4. Dusty,

    I can’t believe you actually wrote up this solution just before I had the same problem. Your work is going to save me hours.

    We’re using folders in a single domain for our blogs. I assume this will work?

    A lot of people can probably use this. We need it for all kinds of standardized terms & conditions, privacy policy, contact pages, and stuff like that.

  5. Well, I was able to get something working. The proper menu items (pages) are listed. But when I click on them I jump to the main blog. And at that point things like the home page link are wrong, so people appear to be on the wrong blog. I think this is the same problem Brian was describing in an earlier comment.

    Here’s an example using folders:

    http://example.com = main blog where I defined the pages that have to appear on all blogs.

    http://example.com/veggies/ = sub-blog1
    http://example.com/seafood/ = sub-blog2

    There are no pages defined in the sub-blogs.

    So using your code when I go to the seafood blog I see the pages from the main blog listed. But when I go to one of those pages the URLs look like:

    http://example.com/a-page/

    And at that point, my links like the following don’t get me back to the seafood blog:

    <a href=”/”>Home

    How do those pages know which blog they are on so they display the proper sidebars and other navigation links to get back to the proper place?

    I hope this question is making sense. Thanks much for any help.

  6. Dusty,

    Thanks for the work so far. I too am looking for a solution similar to what Brian and Robert are working on.

    I have a site that has multiple locations as blogs (including the main blog that isn’t a location) so:

    http://www.site.com/
    http://www.site.com/philadelphia/
    http://www.site.com/new-york/
    etc…

    The main site has pages such as about, team, etc that will be the same for all of the locations. Right now I have to clone a location every time they open a new location and there is information that is always the same across all locations. This means that every time someone wants to change their bio in the about section, 5+ pages of the same information has to be edited.

    Would it be possible to create a custom page template where you just put in the location of the information to clone? So for example my http://www.site.com/philadelphia/about/team page would just have some text “/about/team” and the custom page template would grab the page info from there.

  7. Hi Dusty! Great job!

    I am also looking for this same solution. What I’m trying to do is a have a main blog (1) that I add pages to. Those page links are then displayed in the individual blogs along with the bog owners pages. When you are on, say blog 2, it will display blog 2s navigation then display the main blog navigation as well.

    Now once thats displayed a user reading blog2 will click the link but rather than taking them to blog1 it simply takes them to a blog2 page that pulls the blog1 page info from the database and displays it.

    For example if I create a new “about us” page on blog1. that adds that page to all the blogs. when I edit that page on blog1 all the blogs are updated.

    If anyone knows of a solutions it would be greatly appreciated!

    Thanks to everyone!

  8. Does anyone know if there is another language or set of commands beside SQL for talking with databases?

    I’m working on a project and am doing some research thanks

  9. Great work. It inspired a solution (hack) to my problem of wanting to display a global menu controlled by the bookmarks list of the main blog.
    Problem: once defining the current site as ID 1, I can’t get it to go back to the actual current site to display the user’s own bookmarks list. How do I get the real ID back?
    global $wpdb;
    $wpdb->set_blog_id(1);

  10. Just what I was looking for! However, I have the problem that my WPMU install uses subdirectories instead of subdomains, and I need the page link to point to the page on the main site. Currently, it links to the page of the current sub-site (which doesn’t exist).

    The link I want: domain.com/page
    The link I am getting: domain.com/subsite/page

  11. For all above who where having problems with the sub directories. I added an array of all my sub blogs and then removed them all with the string replace. See $blogs = array below

    // This line is sloppy and needs improvement.
    // You have to remove the name of the blog your currently on from you global navigation.
    // I’m doing this the simplest but least scalable way here.

    $blogs = array(“music/”, “action-sports/”, “new-releases/”,”stuff-we-like/”);
    $output = str_replace($blogs, “”, $output);

    if ( $r[‘echo’] )
    echo $output;
    else
    return $output;
    }

  12. Thank you very much for this code. Works great in WP3.

    I’ve slightly updated the code since CK’s version of URL replacement was still hard-coded stuff, (see CK’s array solution to URL replacement problem) and won’t work fluently when an administrator can add sites that were not there at first release.

    Here is a little trick that worked for me:


    switch_to_blog(1);
    $mainSiteURL = get_bloginfo('url');
    restore_current_blog();
    $output = str_replace(get_bloginfo('url'), $mainSiteURL, $output);

    Of course, you don’t want to switch blog twice, but that’s basically what would work in a generic way.

    Thanks to Felipe Navarro V. comment for pointing out the switch_to_blog function.

Leave a Reply to Dusty Cancel reply

Your email address will not be published.