Create hierarchical navigation for custom post types in Wordpress with PODS

; Date: Sat Jun 20 2015

Tags: Wordpress

On my Wordpress site I want to create "documentation" areas with a cluster of pages organized as a hierarchy, with an index to those pages showing as a sidebar. Many think of doing this for "Product Documentation", but I simply want to organize notes and additional material related to some books that I'm writing. Just as a book is organized by chapters and subsections, I want to hierarchically organize these pages.

As a Drupaler, what I want is the "book" content type but for Wordpress. The Drupal book content type is one of the out-of-the-box features to organize pages in a hierarchy, along with nice hierarchical navigational elements attached to the page automagically.

Apparently one can do this in Wordpress for Pages, but I wanted these pages to be outside the Page list. I use the PODS Framework to help with creating custom content types since it's similar to the effect of adding CCK to a Drupal 6 site. When creating a custom content type in PODS it's simple enough to add hierarchy support, but the problem is how to get the hierarchy to display.

Turns out that Wordpress provides some functions with which to construct the navigational elements.

The first thing to cover is the Next and Previous entries in the book page hierarchy. That seems to be automagically generated by something, presumably Wordpress in supporting Hierarchical node types.

The next thing - and this is what I wanted to show off - is creating a tree structured listing of pages within a particular book page area. While it's fairly easy to do, the steps weren't well documented.

Let's first back up a second to discuss the display of custom fields in a custom post type. The PODS framework doesn't help with this, nor does Wordpress do so out of the box. You can create a custom post type with PODS and add a bunch of fields to that post type, but your visitors won't know anything about that extra data by default.

Therefore it's necessary to create a custom theme file -- actually two of them -- for each custom post type. One custom theme file shows the "excerpt" for Archive pages, and the other shows the Full display for use from single.php. Theoretically the PODS Frontier Auto Template plugin is supposed to be used for displaying custom content of custom post types -- but I couldn't figure out how to do anything useful with that plugin. Hence, the plugin is installed and activated but I'm ignoring it.

In other words, what I'm about to show you is code for the template file for the full display of the custom post type.

With that in mind - in the full display template for your custom post type, add the following:

<?php the_content(); ?>
<?php theme_name_book_show_children($post); ?>

This is going to immediately make page loading for this post type fail. That's good because we know there's a problem, and now we get to fix it.

In the functions.php for your theme add this function:

function theme_name_book_show_children($post) {
    if ($post->post_parent) {
      $post_parent = get_post($post->post_parent);
      ?>
      <ul>
      <li><a href="<?php echo get_permalink($post->post_parent); ?>"><?php echo $post_parent->post_title; ?></a>
      <ul>
      <?php 
        wp_list_pages(array(
           'post_type' => 'book_page',
           'sort_column' => 'menu_order',
           'child_of' => $post->post_parent,
           'title_li' => null
        ));
       ?>
      </ul></li></ul><?php
    } else {
      ?><ul>
      <ul>
      <li><a href="<?php echo get_permalink($post->ID); ?>"><?php echo $post->post_title; ?></a>
      <ul>
      <?php 
        wp_list_pages(array(
           'post_type' => 'book_page',
           'sort_column' => 'menu_order',
           'child_of' => $post->ID,
           'title_li' => null 
        ));
       ?>
      </ul></li></ul><?php
    }
}

That's a fair amount of code, but it's pretty straight-forward. The key is the wp_list_pages function. This function generates HTML for a list of posts, given parameters we pass in through the array.

Since we've created a custom post type, we have to specify it's slug name in the post_type parameter.

The sort_column parameter makes the results make sense within the hierarchical ordering of posts of this custom post type.

The title_li parameter is something I'm doing by hand, rather than letting the wp_list_pages function do it. Passing null like this turns off that feature. The code as I've written it creates an outer ul list, with its item listing the parent post of the tree of posts we're going to display. That way the user can navigate to the parent post fairly easily. Within that it creates another ul list, containing the posts generated using the wp_list_pages function.

Finally we get to the child_of parameter. That parameter tells Wordpress from which post to generate the tree of posts. As it stands we'll go to the parent of the current post (if there is one) or start at the current post.

This code does have a problem - it seems to only go one level deep - and it doesn't go the top-most parent of the page tree that this post belongs to. I'll work on this issue and then update this blog post.

About the Author(s)

(davidherron.com) David Herron : David Herron is a writer and software engineer focusing on the wise use of technology. He is especially interested in clean energy technologies like solar power, wind power, and electric cars. David worked for nearly 30 years in Silicon Valley on software ranging from electronic mail systems, to video streaming, to the Java programming language, and has published several books on Node.js programming and electric vehicles.