Over the past few months, I’ve been working on a new premium theme for WordPress that would feature a single post on the home page. The one issue I needed to overcome was that I wanted that post to appear the same as it would on the single post page, which meant also displaying the comments.
This wasn’t as straightforward as you might think, though I did find a few different ways to make it happen.
Change the WordPress query
The easiest is to just insert two lines of code into the theme’sindex.php file right before the WordPress loop:
is_single = true; ?>Now you can set the Blog pages show at most number to “1” in Settings → Reading and it’ll work. Not too complicated, right? The major issue with this is that you’re tricking WordPress into thinking that the home page is actually a single post page. It’s not the most efficient way to code and you will end up having two pages that display the same content with different URLs, which is a no-no for search engines. A better way to do the same thing (which I still think is a no-no), is to hook into
pre_get_post and change the query a little:
is_home() || ! $query->is_main_query() )
return;
global $withcomments;
$withcomments = true;
$query->set( 'posts_per_page', '1' );
$query->set( 'ignore_sticky_posts', '1' );
}
?>
This is more efficient, though still presents us with the issue of double content.
Check out the WordPress Codex for more info on pre_get_post().
Redirect the template
The only other solution I could think of that would make a single post the home page and not cause double content is to redirect to the latest post automatically. There are a few different ways to accomplish this. Open upindex.php and replace the code with this:
Or if you prefer to hook it all in
functions.php, here the code your need:
add_action( 'template_redirect', 'bavotasan_custom_template_redirect' );
function bavotasan_custom_template_redirect() {
if ( is_home() ) {
$latest_post_ID = get_posts( 'posts_per_page=1&fields=ids' );
wp_redirect( get_permalink( $latest_post_ID[0] ) );
exit();
}
}
You can even add in a little ternary operator to check for sticky posts:
add_action( 'template_redirect', 'bavotasan_custom_template_redirect' );
function bavotasan_custom_template_redirect() {
if ( is_home() ) {
$latest_post_ID = ( $sticky = get_option( 'sticky_posts' ) ) ? $sticky : get_posts( 'posts_per_page=1&fields=ids&ignore_sticky_posts=0' );
wp_redirect( get_permalink( $latest_post_ID[0] ) );
exit();
}
}
Check out the WordPress Codex for more info on template_redirect().
Update
After @Kaspars made some valid points in the comments below, I thought about the redirect and found another approach that might be better. This requires both thepre_get_post() hook and the template redirect, but it eliminated the double content and keeps your home page URL constant.
add_action( 'pre_get_posts', 'bavotasan_custom_pre_get_posts' );
function bavotasan_custom_pre_get_posts( $query ) {
if ( ! $query->is_home() || ! $query->is_main_query() )
return;
global $withcomments;
$withcomments = true;
$query->set( 'posts_per_page', '1' );
$query->set( 'ignore_sticky_posts', '1' );
}
add_action( 'template_redirect', 'bavotasan_custom_template_redirect' );
function bavotasan_custom_template_redirect() {
$latest_post_ID = get_posts( 'posts_per_page=1&fields=ids&ignore_sticky_posts=0' );
if ( is_single( $latest_post_ID ) ) {
wp_redirect( home_url() );
exit();
}
}
You lose the ability to feature a sticky post, though there is probably a workaround that could even make that work. For now, I suggest using this technique.
I’d like to hear what others have to say so feel free to add your thought in the comment section below.
Featured image provided by Gratisography.