It’s easy to use adjacent or previous – next single post navigation when you want WordPress posts sorted by publish date. But often you need to sort posts or custom post types by title alphabetically or by menu order (using page attributes). I’ve always found this difficult, and while there are plugins that should help with WordPress menu order sort, you may still need to edit or create new templates to get it to work.
A workaround, of course, is just to change the publish date of the posts, so that they’re in the correct order, but that’s not always best, so here’s a method to use WordPress menu order for adjacent previous-next single post navigation. So you can just add the code to your child theme functions.php and then add the styles to your style.css. The sort functions work for any WordPress theme, but since I use Genesis Framework, that’s what I used to add the navigation.
https://gist.github.com/mjsdiaz/e492722c13d5faa15589
Note: It’s also easy to sort posts, and custom post types by menu order or title alphabetically on archive pages (blog or categories); you would just use a custom query, so that’s not part of this tutorial.
Overview Explanation
The functions that need to be filtered to alphabetize or to use menu order are in your WordPress install /wp-includes/link-template.php. You can see the $sort filter at 1620. That was always the filter I looked at unsuccessfully. I ran across a code snippet at snipplr.com that also used the $where filter on line 1608 that made it all make sense for me. There is a third filter $join at line 1594, if you want sort within a particular taxonomy. But it’s easier to use the WordPress function get_adjacent_post() for that. You can see the beginning of the query on line 1622.
The Entire Code
This is the entire code section that you would add to your child theme functions.php. The explanations are below. There are two sections; Section 1 filters the WordPress sort and Section 2 adds the adjacent or previous-next navigation to single posts.
<?php
// Do NOT add the line above when you copy.
/** Add previous/next post navigation on book posts.
* http://snipplr.com/view/74493/adjacent-post-by-alphabetical-order-in-wordpress/
* /wp-includes/link-template.php
* line 1608
* $where = apply_filters( "get_{$adjacent}_post_where", $wpdb->prepare( "WHERE p.post_date $op %s AND p.post_type = %s $where", $current_post_date, $post->post_type ), $in_same_term, $excluded_terms );
* line 1620
* $sort = apply_filters( "get_{$adjacent}_post_sort", "ORDER BY p.post_date $order LIMIT 1" );
*/
add_action( 'genesis_entry_footer', 'amethyst_book_post_nav', 16 );
function amethyst_book_post_nav() {
if ( is_singular( 'book-post' ) ) {
global $post, $wpdb;
// Section 1.
function filter_next_post_sort( $sort ) {
$sort = 'ORDER BY p.menu_order ASC LIMIT 1';
return $sort;
}
function filter_next_post_where( $where ) {
global $post, $wpdb;
$where = $wpdb->prepare( "WHERE p.menu_order > '%s' AND p.post_type = 'book-post' AND p.post_status = 'publish'",$post->menu_order );
return $where;
}
function filter_previous_post_sort( $sort ) {
$sort = 'ORDER BY p.menu_order DESC LIMIT 1';
return $sort;
}
function filter_previous_post_where($where) {
global $post, $wpdb;
$where = $wpdb->prepare( "WHERE p.menu_order < '%s' AND p.post_type = 'book-post' AND p.post_status = 'publish'",$post->menu_order );
return $where;
}
add_filter( 'get_next_post_sort', 'filter_next_post_sort' );
add_filter( 'get_next_post_where', 'filter_next_post_where' );
add_filter( 'get_previous_post_sort', 'filter_previous_post_sort' );
add_filter( 'get_previous_post_where', 'filter_previous_post_where' );
// Section 2.
$previous_post = get_previous_post();
$next_post = get_next_post();
echo '<div class="adjacent-entry-pagination pagination">';
if ( $previous_post ) {
echo '<div class="pagination-previous"><a href="' .get_permalink( $previous_post->ID ). '"><span>Previous Chapter</span>' .$previous_post->post_title. '</a></div>';
} else {
echo '<div class="pagination-previous"><a href="' .get_post_type_archive_link( 'book-post' ). '"><span>Chapter Summaries</span>Book Title</a></div>';
}
if ( $next_post ) {
echo '<div class="pagination-next"><a href="' .get_permalink( $next_post->ID ). '"><span>Next Chapter</span>' .$next_post->post_title. '</a></div>';
} else {
echo '<div class="pagination-next"><a href="' .get_post_type_archive_link( 'book-post' ). '"><span>Chapter Summaries</span>Book Title</a></div>';
}
echo '</div>';
}
}
Replace ‘book-post’ with Your Post Type
- The line
add_action( 'genesis_entry_footer', 'amethyst_book_post_nav', 16 );
is the hook to add the adjacent single post navigation just below the entry-footer, but before the end of the entry-content. You can change this hook to place the navigation where you like. - This is for a custom post type with slug ‘book-post’. You would replace that with the slug of your custom post type, everywhere in the code. You may also use ‘post’ as the post type, if you use sort alphabetically.
Explanation of Section 1 Code
- To navigate single posts by menu order, you have to add the
'supports' => array( 'page-attributes' ),
when you create the custom post type. Then in the WordPress editor, add a number in Page Attributes > Order. - For sort by menu order, use it exactly as it is.
- To navigate single posts alphabetically, replace
p.menu_order
and$post->menu_order
withp.post_title
and$post->post_title
. - Again change the post type slug to yours.
Explanation of Section 2 Code
- This is my code to add the post navigation with classes, so that I could style it. I chose classes to go with my theme, but this should work for most themes.
- I also added a link to the archive page when there is no previous or next post; I didn’t want it to be empty.
CSS to Add Styles
Add these styles to your style.css to style the adjacent pagination; you may want to have additional styles for pagination on your archive pages (blog, categories, etc.).
/* Adjacent Pagination
--------------------------------------------- */
.pagination {
clear: both;
margin: 30px 0 0;
}
.adjacent-entry-pagination {
border-top: 1px solid #999;
border-bottom: 1px solid #999;
font-family: Lora, Georgia, serif;
margin: 60px 0 0;
}
.adjacent-entry-pagination .pagination-previous,
.adjacent-entry-pagination .pagination-next {
display: block;
float: left;
padding: 15px 0;
text-align: center;
width: 50%;
}
.adjacent-entry-pagination .pagination-previous {
border-right: 1px solid #999;
}
.adjacent-entry-pagination .pagination-next {
float: right;
}
.adjacent-entry-pagination .pagination-previous a,
.adjacent-entry-pagination .pagination-next a {
color: #454545;
text-decoration: none;
}
.adjacent-entry-pagination .pagination-previous a:hover,
.adjacent-entry-pagination .pagination-previous a:focus,
.adjacent-entry-pagination .pagination-next a:hover,
.adjacent-entry-pagination .pagination-next a:focus {
color: #4251ce;
text-decoration: underline;
}
.adjacent-entry-pagination .pagination-previous span,
.adjacent-entry-pagination .pagination-next span {
display: block;
font-style: italic;
}
.adjacent-entry-pagination .pagination-previous span::before,
.adjacent-entry-pagination .pagination-next span::after,
.archive-pagination .pagination-previous a::before,
.archive-pagination .pagination-next a::after {
content: "\f341";
display: inline-block;
-webkit-font-smoothing: antialiased;
font: normal 18px/1 'dashicons';
padding: 0 3px 3px 0;
vertical-align: middle;
}
.adjacent-entry-pagination .pagination-next span::after {
content: "\f345";
}
I used WordPress dashicons to add the arrows; you can read more about adding dashicons or about using the dashicon arrows.
There you are with nice adjacent single post navigation for your theme.
Leave a Reply