The question:
I’ve been reading this by @nacin and getting to grips with wp_query over query_posts that I used to use.
What I want is:
-
to put this in a template file
-
to query all posts of this category, in this case ‘3’
-
to display, if available, the first result on the page the latest sticky post
-
after the first sticky, if one is set, display the rest of the posts excluding that sticky if it was set
Problems I have seen are:
– if I do posts_per_page = 1 on the sticky loop, I can not do posts_per_page = -1 on the rest of the posts loop. To workaround this I’ve just set the number to 999.
I should say now that the code I have works. However this is for a very high traffic site, and I want to make sure this is the best way of doing it, and I’m not sure I’m using wp_query right to do this since the original query’s are essentially the same as one another just with and without sticky posts.
global $wp_query;
$wp_query = new WP_Query(array(
'post_type' => 'post',
'posts_per_page' => 1,
'category__in' => 3,
'post__in' => get_option( 'sticky_posts' )
));
while ($wp_query->have_posts()) : $wp_query->the_post();
$exclude_featured = $post->ID;
echo the_title();
echo '<br />';
endwhile;
echo '<br />';
echo '<br />';
global $wp_query;
$args = array_merge(
$wp_query->query_vars,
array(
'post__in' => null,
'posts_per_page' => 999,
'ignore_sticky_posts' => 1,
'post__not_in' => array($exclude_featured)
)
);
query_posts( $args );
while ($wp_query->have_posts()) : $wp_query->the_post();
if ( $exclude_featured == get_the_ID() )
continue;
echo the_title();
echo '<br />';
endwhile;
Thanks for any help guys.
The Solutions:
Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.
Method 1
you could use wp_list_pluck();
if ( $exclude_featured )
$args['post__not_in'] = wp_list_pluck( $exclude_featured->posts, 'ID' );
$args['posts_per_page'] = 999;
query_posts( $args );
endif;
while ( have_posts() ) : the_post();
...
Method 2
Here is the really simple way to do it.
$args = array(
'posts_per_page' => -1,
'category__in' => 3,
'ignore_sticky_posts' => 0
);
$my_custom_query = new WP_Query( $args );
while ( $my_custom_query->have_posts() ) :$my_custom_query->the_post();
<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
//Your Stuff
endwhile;
// Reset Post Data
wp_reset_postdata();
- No need to use
global $wp_query;
especially 2x. - No need to echo
br
tags…several times if your using the<?php post_class();
Use CSS, that way you will automatically get a class called.sticky
! - Use a better name for your query.
Here is an update using 2 queries to address the details I missed, since it will be somewhat safe.
// **Loop 1** get the first sticky only
$sticky = get_option( 'sticky_posts' );
$the_query = new WP_Query( 'p=' . $sticky[0]);
while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
// your content
<?php endwhile; wp_reset_postdata(); ?>
//////////////
//**Loop 2** exclude the sticky from the Loop 1
$args = array(
'posts_per_page' => -1,
'ignore_sticky_posts' => 1,
'post__not_in' => array($sticky[0])
);
$super_query = new WP_Query($args);
while ( $super_query->have_posts() ) : $super_query->the_post(); ?>
<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
// your content
<?php endwhile; wp_reset_postdata(); ?>
Method 3
I see 2 major problems. a) You shouldn’t modify a global variable directly & b) You shouldn’t use query_posts
. Here’s a reworked example
functions.php
add_action('pre_get_posts', 'customize_query');
function customize_query($query) {
if(!$query->is_main_query() || !is_page_template('template-file-name.php'))
return;
$wp_query = new WP_Query(array(
'post_type' => 'post',
'posts_per_page' => 1,
'category__in' => 3,
'post__in' => get_option( 'sticky_posts' )
));
$query->set('posts_per_page', -1);
$query->set('ignore_sticky_posts', 1);
if(!empty($wp_query->posts))
$query->set('post__not_in', array($wp_query->posts[0]->ID));
}
in the template file
$query = new WP_Query(array(
'post_type' => 'post',
'posts_per_page' => 1,
'category__in' => 3,
'post__in' => get_option( 'sticky_posts' )
));
while ($query->have_posts()) : $query->the_post();
echo the_title();
echo '<br />';
endwhile;
echo '<br />';
echo '<br />';
while (have_posts()) : the_post();
echo the_title();
echo '<br />';
endwhile;
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0