What I’m trying to do is display the most recent post (a la my theme’s “single.php”) on my “home” page.
This is complicated by the fact that I have certain plugins (specifically, Scripts n Styles) that are hooking wp_head and wp_enqueue_scripts. In these hooks, they are checking is_singular() to see if my per-post javascript should be injected into the page or not. They then check attributes of the global $post variable to determine which scripts to inject. I want the per-post javascript to be properly injected on the home page if needed.
For reference, the plugin in question’s source code is here and the specific function I’m concerned with running properly is called scripts_in_head()
:
static function scripts_in_head() {
// Global
$options = get_option( 'SnS_options' );
if ( ! empty( $options ) && ! empty( $options[ 'scripts_in_head' ] ) ) {
?><script type="text/javascript" id="sns_global_scripts_in_head"><?php
echo $options[ 'scripts_in_head' ];
?></script><?php
}
if ( ! is_singular() ) return;
// Individual
global $post;
$SnS = get_post_meta( $post->ID, '_SnS', true );
$scripts = isset( $SnS['scripts'] ) ? $SnS[ 'scripts' ]: array();
if ( ! empty( $scripts ) && ! empty( $scripts[ 'scripts_in_head' ] ) ) {
?><script type="text/javascript" id="sns_scripts_in_head"><?php
echo $scripts[ 'scripts_in_head' ];
?></script><?php
}
}
I’m pretty new to WordPress development, so I’ve probably made a boneheaded mistake here that is making my life overly difficult. Here are the various and sundry ways I’ve beaten my head against the wall:
From what I understand, I can’t just change my home.php
template, since the template isn’t even executed until after all these hooks would have already run. Therefore, modifying the query at this point or creating a new one would be pointless.
I could use a HTTP header redirect, although I’m not sure that would work without manually updating the redirect every time the latest post changes.
I could change home.php
to have a javascript redirect, but that seems like it would be a lot of time/effort wasted loading the “dead” home page just to get redirected to another page. If this is the only way, so be it, but it seems like I should be able to do better.
I’ve tried creating a plugin that hooks earlier than Scripts n Styles, and modifies $wp_query, but this doesn’t seem to work properly. Likely, I’m doing it wrong:
function make_single_from_home()
global $wp_query;
if ( $wp_query->is_home() ) {
$last = wp_get_recent_posts( '1');
$last_id = $last['0']['ID'];
$wp_query->set( 'p', $last_id )
$wp_query->set( 'post_count', 1);
$wp_query->set( 'is_home', false);
$wp_query->set( 'is_single', true);
}
}
I’ve tried attaching this to several events prior to Scripts n Styles’ hook, (send_header, template_redirect, etc), and it doesn’t seem to help. I don’t see the javascript blocks being added to my <head>
tag. (It’s possible that this is a valid solution and I or the plugin are just Doing It Wrong)
It’s also possible that there’s a really easy way to make my homepage a singular page displaying my latest post, and I’m just too new to figure it out.
Is there some way to create a home page that displays just the latest post, while making the $post
variable valid, and is_singular() == true
early enough for my plugin dependencies?
I’m not sure how plugin hooks would impact in any way the solution to your problem. The
home.php
template file gets included at thetemplate_redirect
action, which fires well-beforewp_head
.That said, what it sounds like you want to do is:
'posts_per_page' = 1
on the first page of the blog posts index'posts_per_page' = 10
on subsequent pages of the blog posts indexThe simplest method is probably to use a static page as the site front page, and then use a custom query in
front-page.php
to retrieve the latest post.front-page.php
:Since
is_singular()
returns true for static pages as the site front page, your plugin script enqueues should be unaffected.Chip’s answer helped me fix the error, but it took a bit more tweaking to get it fully solved.
With a static front page, the
front-page.php
template will be called (as per the hierarchy) with$wp_query
populated with page ID that corresponds to the page you’ve chosen to show as the “static page” in the reading options.Chip suggested creating a new query after the
get_header()
call, which can help change the posts that are displayed. He’s also correct that, owing to the settings parsed into$wp_query
to thefront-page.php
template, theis_singular()
call will returnTRUE
.However, this won’t solve the issue of the value of
$post
. As soon asget_header()
is called, most themes will advance the action chain fromtemplate_redirect
pastwp_enqueue_scripts
. Any hooks in between there will be called, and it will be too late to effect the value of$wp_query
or$post
for plugins that hook one of the events in that region.Therefore, the
wp_head
action was getting called with the$post
information from the “static page” entry. Since I don’t want that to happen, I have to modify these values somehow prior to the call toget_header()
.There are probably multiple ways of doing this, but the one that worked for me was to add:
to my
front-page.php
prior to the call toget_header()
. This overwrites the query value generated from the static page, and replaces it with one that returns just the most recent post.It’s probably possible to do this with a plugin as well, so long as you hook early enough.
You are trying to display a snippet of JavaScript on the homepage, which features a single post.
The simplest way is to include the snippet of JS everywhere (Global Settings), then check in the JavaScipt whether you are on the homepage:
if ( $('body').hasClass('home') ) { /* do_stuff() */ }
This will simplify your maintenance of code.
(Sorry I didn’t ever see this until now.)