WordPress: Display post links on a specific page

Since I have modified the theme called Zombie-Apocalypse I use here on this site to display, I thought I’d share it here what I did exactly.

First I started by adding a custom_field to each post to specify the type of the post.
I named the custom_field “article_type”, and the values so far used are “howto” or “review”. At some point probably more will be added. Then I modified the page.php, which is responsible for the, as the name says, wordpress pages. Right at the start of the code, directly underneath the author’s comment I added

global $post; 
if ($post->post_name == 'articles')
{
    $myposts = get_posts('numberposts=-1');
    $myarticles = array();
    foreach($myposts as $mypost)
    {
        $myarticles[$mypost->ID] = get_post_meta($mypost->ID,'article_type',true);
    }
} 

Since I want to have the posts only displayed on the page called ‘article’, the if condition checks if the page is indeed the page needed.
Followed by that I get all available posts through using the wordpress function get_posts(), passing the parameter ‘numberposts=-1’, -1 in order to get all posts, since the default is to get the latest 5 posts.

The object I have now I iterate through a foreach loop into an array getting the custom meta I set in each post using get_post_meta(), parameters being the post ID of the iterated post, the custom field’s name and the boolean true to return one value only. That’s it for this part.

Further down the code I look for the_content(). This function’s responsible to print out your page’s content. Underneath I add this:

if ($post->post_name == 'articles')
{
   print "<h4>Howtos</h4>";
   foreach ($myarticles as $k=>$v)
   {
      if ($v == 'howto')
      {
         $the_article = get_the_title($k);
         $the_article_perma = get_permalink($k);
         print "<a href = '".$the_article_perma."'>".$the_article."</a><br />";
      }   
   }
   print "<p><br /></p>";
   print "<h4>Reviews</h4>";
   foreach ($myarticles as $k=>$v)
   {
      if ($v == 'review')
      {
         $the_article = get_the_title($k);
         $the_article_perma = get_permalink($k);
         print "<a href = '".$the_article_perma."'>".$the_article."</a><br />";
      }
   }
}

What I did here is fairly simple. For each article_type I have, I print a small header, followed by an iteration of my array. While iterating I check if the value is the article_type I want, and if that’s the case, get the post’s title, it’s permalink and print it out.

That’s all I did to the page.php to display posts with a certain custom_field meta on a specific page.

The next modification I’ve done is in single.php, displaying the posts. There I’ve replaced the given navigation, which links to the previous and next adjacent post of the current viewed post to instead link to the previous and next post with the same custom_field meta, resulting in the navigation letting you browse through all reviews if you are reading a review, or browsing through all howtos while reading a howto.

Underneath the intro comment, above the get_header() I inserted following code:

global $post,$wpdb;
$current_meta = get_post_meta($post->ID,'article_type',true);

$previous_post_same_meta = $wpdb->get_var($wpdb->prepare(sprintf("SELECT post_id FROM wp_postmeta 
WHERE meta_key = '%s' AND meta_value = '%s' AND post_id < '%s' ORDER BY 
post_id DESC LIMIT 1", "article_type", $current_meta, $post->ID)));

$next_post_same_meta = $wpdb->get_var($wpdb->prepare(sprintf("SELECT post_id FROM wp_postmeta 
WHERE meta_key = '%s' AND meta_value = '%s' AND post_id > '%s' ORDER BY 
post_id ASC LIMIT 1", "article_type", $current_meta, $post->ID)));

function print_custom_nav($nav_post_id,$previous=true)
{
    return sprintf(
        "<div class='%s'><a rel='%s' href='%s'>%s</a></div>",
        $previous ? 'nav-previous' : 'nav-next',
        $previous ? 'prev' : 'next',
        get_permalink($nav_post_id),
        $previous ? '<span class=\'meta-nav\'>&larr; </span>'.get_the_title($nav_post_id) 
        : get_the_title($nav_post_id).'<span class=\'meta-nav\'> &rarr;</span>'
    );
}

Here I need to use the wordpress DB class, $wpdb, since there’s no available function to let me get the adjacent posts of the current with a specific custom_field meta. Two queries are used, one to get the previous post with the same custom_field meta, and one for the next post.

Since four replacements need to be done for the links, I use a function to return the html for the links ready to be printed out.

In this theme the navigation can be found between <div id=”nav-above” class=”navigation”> </div> and <div id=”nav-below” class=”navigation”> </div> respectively.

Delete / comment out the current code there and insert

if ($previous_post_same_meta)
{
   print print_custom_nav($previous_post_same_meta);
}

if ($next_post_same_meta)
{
   print print_custom_nav($next_post_same_meta,false);
}

Badabing, the nav is there again, displaying the adjacent posts with the same custom_field meta, if there’s a post.

The whole point for me doing this was to keep the complete wordpress navigation fairly simple. This way I have the page ‘articles’ at the URI http://www.regendoerp.com/articles/, while all posts are listed in the category with the same name, ‘articles’, therefore resulting in posts being at the URI http://www.regendoerp.com/articles/the_post. This makes the whole thing just look neater.

For this the permalinks setting in the wordpress admin menu is set to ‘Custom Structure’ with the value being ‘/%category%/%postname%/’.

This should be easy to adapt to any other theme. Adjustments may be necessary, depending how the theme’s coded, in some themes you may also have to place this code in a different file than page.php and single.php.

Enjoy!