Alexander Blackman

Perch Blog Navigation

For my blog I wanted to have a simple link to navigate between the next or previous post. I went searching for solutions, trawling through the Perch support forum and even looking at things like the 24 Ways code on GitHub.

I eventually came across a solution by Marc Sanders in the old Perch forum, so I grabbed the code and pasted it in as is. Success! It worked beautifully all the way until I got to the first or last post, then something went wrong. Damn!

After some experimenting, I began to realise that there was an issue with the way the $prev and $next functions were working. In Marc’s version, the code relied on there always being a previous or next post. As soon as there wasn’t (as with the first and last posts), the function would be empty. While there was fall back code in the HTML templates, because the function was empty the HTML templates never made it. No template meant no markup, so the code would break.

I also was not sure what version of Perch Marc’s code was intended to work with, but as the rest of the code did work, I decided to tweak Marc’s version and came up with the following:

Post.php

<?php

$slug = perch_get('s'); // sets slug to equal postSlug

$html = perch_blog_post($slug, True);  // stores post in variable to use later

$data = perch_blog_custom(array(
    'filter'=>'postSlug',
    'match'=>'eq',
    'value'=>$slug,
    'skip-template'=>true, 
)); // grabs data of current post

$data = $data[0]; // not sure why this is required, but code breaks without it

$date = $data['postDateTime']; // sets the date variable to the posts published date

$prev = perch_blog_custom(array(
    'count'=>1,
    'filter'=>'postDateTime',
    'match'=>'lt',
    'sort'=>'postDateTime',
    'sort-order'=>'DESC',
    'value'=>$date,
    'template'=>'blog/post_prev.html'
), true); // stores post in a variable to use later

$next = perch_blog_custom(array(
    'count'=>1,
    'filter'=>'postDateTime',
    'match'=>'gt',
    'sort'=>'postDateTime',
    'sort-order'=>'ASC',
    'value'=>$date,
    'template'=>'blog/post_next.html'
), true); // stores post in a variable to use later

?>

<?php
    if ($html) {
        echo $html; // display post
    }

    if (empty($prev)){
        echo '<div class="blog-nav"><a class="disabled">Prev</a>';
    } else {
        echo $prev;
}

if (empty($next)){
    echo '<a class="disabled">Next</a></div>';
} else {
    echo $next;
}

?>

Post_prev.html

<div class="blog-nav">
    <a href="/articles/<perch:blog id="postSlug" />" class="prev">Prev</a>

Post_next.html

<a href="/articles/<perch:blog id="postSlug" />" class="next">Next</a>
</div>

How it works. Sort of

A key component of what makes this code work, is that the first php block is just getting the relevant data and storing it within variables, which the second block then uses to display the post and the links.

The clever bit for generating the URLs for the previous and next posts is in the $prev and $next variables. Here, the database (that contains the blog posts) is being queried relative to the postDateTime of the post you happen to be looking at (this is what the top half of the code does). The $prev variable is then filtering records that are “less than” the current post’s postDateTime. That is, posts which were published before the current post. The $next variable works the other way, filtering records that were published after (greater than) the current post. The template in each of these variables then receives the relevant postSlug to generate the link URL.

Once all the data for the current post ($html), previous post ($prev) and the next post ($next) has been retrieved, the second php block then displays the content. The basic if/else statement ensures the markup is always complete, even if the $prev or $next variables happen to be empty.

While this code works, I would be lying if I said I knew exactly how. In particular I’m not sure about $data = $data[0]; as I do not know why it is needed; however without it the rest of the code breaks. Also if you need to filter posts by more than one criteria – such as categories or tags – I do not know if it will work at all.

While this code is not “battle tested”, hopefully it is of some use to others (like me) who are trying to get previous and next URLs for their blogs posts. I have posted this solution to the (new) Perch forum and it is also available from GitHub.

—Alex
22 May 2015

Back to start Previous: Next: