WordPress Navigation or Page List: Complex Sidebars

WordPress Logo

Navigation: when the pages have pages…

I’m working on a relatively large site for a client right now…about 200 pages deep, give or take. One of the sections of the site contains various shopping and dining pages. Each of these pages are using a two-column, sidebar layout. The shopping pages needed to include a list of all of the other shopping pages, the dining pages all of the other dining pages. To make it more complex, each list of pages needed to be grouped together in the sidebar according to their locations. Some of these groupings included nearly twenty pages, others only one or two. The only place that these lists appeared in the sidebar were on the pages in question.

So…is this really a navigation?

Well, no, not really. From the user’s perspective, it functions as though it were a secondary, or utility, navigation, and that would initially cause us to see it as such, certainly. Examining this more closely, however, we see that this is more of a list of pages, not an actual navigation…similar to how pages in your sitemap could be grouped together, for example, separately from posts. That’s a bit of apples and oranges, I’ll give you, but it’s the same principle. This is important, because it changes how we think of it when developing the site. Specifically for WordPress, are we approaching it by adding a menu to the theme, or are we approaching it by using WordPress’ wp_list_pages() function? That difference actually makes all the difference in the world.

When a navigation is a menu

There are times where you want a WordPress menu in your sidebar. WordPress even provides us with a handy widget for just that functionality. When I built Steve Burch Electric, the client wanted brief, individual pages that listed the services offered by the business. There was also a page giving an overview of the services offered. This is the page that lived in the site’s main navigation. The individual services were linked to from a secondary navigation appearing on both that services overview page, as well as each of the individual service pages (which generally are never landed on, as I brought in their content with an Ajax-like fade on click). This made complete sense to register as a second menu. It’s limited in scope, contains a defined list of pages, and is easy for the client to edit. I think that they key here is scope.

This navigation has a had a few too many…

The issue with the current site is just what I mentioned: a problem of scope. Because the dining page sidebars, for example, aren’t just listing all of the dining pages, they are listing the dining pages grouped together by location. Each shopping and dining page (and there were other pages besides shopping and dining that were listing pages in the sidebar, I’m just confining the illustration to those two for the moment) wasn’t just listing all of the shopping or dining pages, they were listing up to three different distinct groupings of dining or shopping pages. To make each of these a menu would have resulted in no fewer than eight additional menus registered for the theme. There was already a main menu, and two menus in the footer, which would have brought the total count to eleven menus for the theme, some with as few as one or two pages. That’s a lot of overhead, and I’ve seen WordPress sites max out execution times because of heavy menu usage in certain server environments. So, in short, building each of these navigations as WordPress menus would have been a completely wrong approach.

But…they’re not just lists, either

So, the obvious solution is to use the wp_list_pages() function with the child_of  parameter. Of course, the simple solution is never what really works out, is it? In this case, that wouldn’t work, for a couple of reasons. First, the individual locations that grouped the dining and shopping pages together didn’t have their own pages…so, for example, there might be fifteen shops listed under Location A, but Location A doesn’t have it’s own page. Also, there were situations in which the same shop or restaurant belonged in two different locations. So, structuring the store pages hierarchically wouldn’t work in this scenario. What to do…?

Enter the magic of Pods

Pods is a go-to plugin for my development workflow, because of how easy it makes so many things. After puzzling over this situation for a bit, the answer was to create page categories. Of course, WordPress doesn’t include this taxonomy for pages out-of-the-box…categories and tags are reserved for posts. In the right situations, though, this sort of taxonomy is very useful in organizing large sites. Specifically, this allowed me to group pages together both in a “dining” or a “shopping” category, as well as assigning categories for their specific locations. It also gives the client the benefit of grouping pages together for internal organization purposes moving forward (which is handy for a 200 page site). Pods makes the process of registering custom post types and custom taxonomies, among other things, extremely simple. It’s built by Automattic, so you know it’s going to work smoothly.

To create a custom taxonomy in Pods, you begin by creating a new pod, and selecting Custom Taxonomy.

Creating a Custom Taxonomy in Pods to use in Navigation

 

Work through the Labels field as it suits you in the following screen. Under Admin UI, choose the Default option under Menu Location if you want the category to display on each page’s editing screen (that’s usually the good choice). I also think it’s a good idea to select Show Taxonomy Column on Post Types. This will add the taxonomy to, in this case, the list of pages when you select Pages > All Pages. This is handy because it will also make the taxonomy available in the Quick Edit option for each page on that screen.

Editing the Custom Taxonomy in Pods to use in Navigation

 

For Advanced Options, it’s always a good idea to keep Query Var checked. Finally, under the Extra Fields tab, there’s no need to enable this option in this case. Your database doesn’t need the extra table.

Finalizing the Custom Taxonomy in Pods to use in Navigation

 

And, that’s it. Click Save Pod, and you have yourself a spiffy new custom taxonomy.

Now, give those pages a place to belong

Now, I simply grouped each dining page into two categories: “dining” (this will become important later), and the location (“location 1 dining,” “location 2 dining”, etc.). I did the same for the shopping pages. This site also included an overview dining page and an overview shopping page, which received the general “dining” or “shopping” category.

Now, to the sidebar. There were not other widgets displaying in the sidebar for these pages (I used the Widget Logic plugin to isolate widget displays to specific pages), only these page lists. So, in sidebar.php, I ran a quick conditional to check if the current page was in either the “dining” or “shopping” categories (many other pages use the sidebar, so we can’t assume that either category will exist, and there’s no need to create a separate sidebar file for this). If they were, I then pulled in a corresponding template part, which is where the actual listing would take place. This modularizes the code according to WordPress best practices, and makes everything clean and easily maintainable. So, my sidebar.php file:

<section class="widget-area" role="complementary">
<?php dynamic_sidebar( 'sidebar-1' ); ?>
<?php
//For dining or shopping pages: pull in the correct page lists based on page category
if(has_term('dining', 'page_category', $post->ID)){
get_template_part('sidebar', 'dining');
}
elseif(has_term('shopping', 'page_category', $post->ID)){
get_template_part('sidebar', 'shopping');
}
?>
</section><!-- ends widget-area -->
view raw sidebar.php hosted with ❤ by GitHub

As I said, this site had more than just those two categories, but this gives you the idea. WordPress’s has_term() function checks the current page’s taxonomy terms: the term is the first argument, the taxonomy the second, and the ID of the page being checked (in this case, always the current page) the third.

Now, to the template parts. This is where I used the different location categories to generate the list of pages. This required a new instantiation of WP_Query to check for each taxonomy, and place them under the headings for each grouping. So, the dining template for example:

<h5><?php _e('Dining Location 1', 'mytheme'); ?></h5>
<ul>
<?php
$dining1 = new WP_Query('post_type=page&page_category=dining-location-1&posts_per_page=-1');
if($dining1->have_posts()):while($dining1->have_posts()):$dining1->the_post();
?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endwhile; endif; wp_reset_query(); ?>
</ul>
<h5><?php _e('Dining Location 2', 'mytheme'); ?></h5>
<ul>
<?php
$dining2 = new WP_Query('post_type=page&page_category=dining-location-2&posts_per_page=-1');
if($dining2->have_posts()):while($dining2->have_posts()):$dining2->the_post();
?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endwhile; endif; wp_reset_query(); ?>
</ul>
<h5><?php _e('Other Dining Locations', 'mytheme'); ?></h5>
<ul>
<?php
$otherdining = new WP_Query('post_type=page&page_category=other-dining-locations&posts_per_page=-1');
if($otherdining->have_posts()):while($otherdining->have_posts()):$otherdining->the_post();
?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endwhile; endif; wp_reset_query(); ?>
</ul>

Making sure to check for pages in each category is important here, so that the code will fail gracefully if the users decide to remove all dining from location 1 at some point in the future, for example. Also, setting the posts_per_page=-1 parameter to each query over-rides the default posts per page in your site’s settings to make certain all of the pages will be listed, regardless of the number.

And there you have it. For this particular site, this was a great solution for lists that were too numerous for menus, but not organized in such a way that simple page lists were feasible. Giving the client more organizational capability over their pages moving forward was an added benefit.

Let me know what you think!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.