On the search results page (search.php
) I would like to perform an additional WP_Query
to keep a specific order of search result types e.g. search results from authors should always be shown before the other results –
The first few pages should hold the author results, the other results should be shown on all the following pages only (not mixed on each page).
global $wp_query; //holds the results of the initial search query
$authorposts = $wp_query->posts;
$query = new WP_Query( 'year=2012&monthnum=12&day=12' );
$otherposts = $query->posts;
$wp_query->posts = array_merge( $authorposts, $otherposts );
$wp_query->post_count = count( $wp_query->posts );
if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
//show results loop...
The problems appear with the behaviour of pagination – while the $authorposts
seem to paginate correctly i.e. correct page numbers for author posts and pagination works as only those where existent. But the $otherposts
on the other hand are shown at the bottom of each page, right under the author posts. And they are the same on every page! Also the page count reflects the count of the first query only.
I have also tried to merge with the plus
operator:
$wp_query->posts = $authorposts + $otherposts;
but in this scenario the $otherposts
don’t show up at all and the page count stays the same (page count for author posts).
All the examples with similar goals using two separate queries I’ve seen looked quite the same –
So I’m wondering if the my way of extending the original search query results with that additional WP_Query
is sufficient or if I’m missing some $wp_query
fields to be populated (correctly)? What’s the correct way doing this?
Update: It should be noted that I’m using the WP-PageNavi plugin to paginate but this should not be relevant in the first place as the first page is already rendered wrong. And it’s also initialized with the query object: wp_pagenavi( array( 'query' => $wp_query ));
I think the only solution is to skip the sql pagination and handle it only via php.
My idea involves 2 functions, one hooked on
pre_get_posts
, the second to filterthe_posts
.The first function does 2 things:
paged
value in global variable, in this way can be used in the second function that run laterHere the function:
Now the search query return all the posts, with no pagination, and the paged required is saved in the global variable
$the_original_paged
.So we can filter
the_posts
merging the wanted additional posts, then get only the correct posts based on required page and posts per page setting, and finally reset thepaged
and other$wp_query
properties to let pagination link works:Filter the main query to include the additional posts. You can add query params with
pre_get_posts
or modify the SQL withposts_request
orposts_where
.Filter
posts_results
orthe_posts
to arrange the returned posts.I could not completly solve all the issues involved in this question but for reference I post the current state here:
What it does:
max_num_pages
of the first query is exceededWhat doesn’t work:
Still I’m amazed that there is no easy approach. In case anybody is able to solve these issues based on my answer (copy+paste) I’d be happy to mark it as accepted!