WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

For a single custom post type, I'm using previous_post_link and next_post_link with simple arrows. (Although text arrows are shown here, in the actual I'm using graphics with the text hidden via CSS.) Code:

<nav class="arrowNav">
    <div class="nav-previous">
       <?php previous_post_link('%link', '«'); ?>

    <div class="nav-next">
       <?php next_post_link('%link', '»'); ?>

This works fine except for the edge cases. I'd like the posts to wrap around: that is, for the first post, I'd like previous_post_link to link to the last post, and for the last post next_post_link would link to the first post. It appears the default for both those cases is null. How do I test for first and last post status and produce links for each?

share|improve this question
up vote 1 down vote accepted

Add following custom functions in functions.php file and instead of calling previous_post_link and next_post_link functions call custom_next_post_link and custom_previous_post_link custom functions respectively.

 function custom_adjacent_post_link( $format, $link, $in_same_cat = false, $excluded_categories = '', $previous = true ) {
if ( $previous && is_attachment() )
        $post = get_post( get_post()->post_parent );
        $post = get_adjacent_post( $in_same_cat, $excluded_categories, $previous );

if ( ! $post ) {            
    $post =  '';
    $args = 'posts_per_page=1&orderby=date&ignore_sticky_posts=1';

        $args .= '&order=DESC';
        $args .= '&order=ASC';

   $the_query = new WP_Query( $args );
    while ( $the_query->have_posts() ) :
         $post = get_post(get_the_ID());   

$title = $post->post_title;

if ( empty( $post->post_title ) )
        $title = $previous ? __( 'Previous Post' ) : __( 'Next Post' );

$title = apply_filters( 'the_title', $title, $post->ID );
$date = mysql2date( get_option( 'date_format' ), $post->post_date );
$rel = $previous ? 'prev' : 'next';

$string = '<a href="' . get_permalink( $post ) . '" rel="'.$rel.'">';
$inlink = str_replace( '%title', $title, $link );
$inlink = str_replace( '%date', $date, $inlink );
$inlink = $string . $inlink . '</a>';

$output = str_replace( '%link', $inlink, $format );
$adjacent = $previous ? 'previous' : 'next';
echo apply_filters( "{$adjacent}_post_link", $output, $format, $link, $post );
function custom_previous_post_link($format='&laquo; %link', $link='%title', $in_same_cat = false, $excluded_categories = '') {
custom_adjacent_post_link($format, $link, $in_same_cat, $excluded_categories, true);
function custom_next_post_link($format='%link &raquo;', $link='%title', $in_same_cat = false, $excluded_categories = '') {
custom_adjacent_post_link($format, $link, $in_same_cat, $excluded_categories, false);
share|improve this answer
Thanks Vinod! This works fine and I think will work for me in other contexts. Wish the standard versions had wraparound capability. – boomturn Mar 6 '13 at 19:24

The accepted answer works, but probly should have used get_posts() instead of a whole wpquery and loop:

    if ( ! $post ) { 
    $args = array('posts_per_page'=> 1,
            'orderby'=> 'date',
            'ignore_sticky_posts' => 1
    $adjposts = get_posts($args);
    $post = $adjposts[0];   

It's generally frowned upon to use wpquery if you dont need to. With full credit, otherwise, to Vinod Dalvi.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.