I have a question today. I am looking for a solution to make sticky post available on my website. But, i just got it work on homepage with the code below.
function wpb_latest_sticky() {
/* Get all sticky posts */
$sticky = get_option( 'sticky_posts' );
/* Sort the stickies with the newest ones at the top */
rsort( $sticky );
/* Get the 5 newest stickies (change 5 for a different number) */
$sticky = array_slice( $sticky, 0, 5 );
/* Query sticky posts */
$the_query = new WP_Query( array( 'post__in' => $sticky, 'ignore_sticky_posts' => 1 ) );
// The Loop
if ( $the_query->have_posts() ) {
$return .= '<ul>';
while ( $the_query->have_posts() ) {
$the_query->the_post();
$return .= '<li><a href="' .get_permalink(). '" title="' . get_the_title() . '">' . get_the_title() . '</a><br />' . get_the_excerpt(). '</li>';
}
$return .= '</ul>';
} else {
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();
return $return;
}
add_shortcode('latest_stickies', 'wpb_latest_sticky');
I was thinking to make the sticky post to be displayed on search, tag, and category as well.
Any solution? Thanks!
This same exact question was asked earlier this week or over the weekend, and it had me thinking. Here is the idea that I came up with.
If you look at the source code of the WP_Query
class, you will see that sticky posts is only added to the first page of the home page. There is also no filter supplied to change this behavior in order to set the required templates according to your liking.
There are many ways to display sticky posts on other templates through widgets, custom queries, shortcodes (which I will not recommend due to the fact that using do_shortcode()
is slower that using the function itself) or custom functions where you need to display them. I have opted to go with using the_posts
filter and pre_get_posts
action.
HERE’S HOW:
-
Get the post ID’s saved as sticky posts with get_option( 'sticky_posts' )
-
Remove this posts from the main query with pre_get_posts
. As stickies are included on the home page, we will exclude the home page. We will also exclude normal pages
-
Inside a custom function, run a custom query with get_posts
to get the posts set as sticky posts.
-
Merge the returned array of sticky posts with the current returned posts of the main query with array_merge
-
Hook this custom function to the_posts
filter
Here is the code: (Requires PHP 5.4+)
add_action( 'pre_get_posts', function ( $q )
{
if ( !is_admin()
&& $q->is_main_query()
&& !$q->is_home()
&& !$q->is_page()
) {
$q->set( 'post__not_in', get_option( 'sticky_posts' ) );
if ( !$q->is_paged() ) {
add_filter( 'the_posts', function ( $posts )
{
$stickies = get_posts( ['post__in' => get_option( 'sticky_posts' ), 'nopaging' => true] );
$posts = array_merge( $stickies, $posts );
return $posts;
}, 10, 2);
}
}
});