Reputation: 737
I am trying to create a custom search results page where Woocommerce product results are displayed separately to blog / general posts.
My aim is to display them as separate blocks with different styling.
[Block 1] - Woocommerce results
[Block 2] - Blog / Post results
I have managed to display the products in one loop, but I am struggling to exclude products from the post loop.
I have tried creating a custom loop, however this just displays all the posts within those terms, rather than the posts returned in the search.
The loop I usually use is:
<?php $loop = new WP_Query( array( 'post_type' => 'post' ?>
<p>Something here</p>
<?php endwhile; wp_reset_query(); ?>
However I believe this just isn't compatible and suitable for my needs.
If there's a better solution to separating these I would absolutely love to hear more.
Upvotes: 2
Views: 1417
Reputation: 20745
The problem you are having is that you have one main query, where you actually want to do two queries. You could of course modify the main query to contain both post types, but you would end up with a random number of both post types where you actually want to fill both columns.
If you modify the main query to only return one of the columns, you end up with a situation where it is awful to run the other query to get the rest of the posts. I think you should be able to use the posts_join
and posts_where
filters if you need them, but I am unsure about posts_search
. You can use either WP_Query
or get_posts
to finally do the two queries you need.
<?php
// Since we are searching, we probably should get the search keyword
$search = get_query_var('s');
// Since we want to be able to navigate, we probably should figure out on which page we are
$paged = get_query_var('paged');
// Anything else we want to do in search queries we should be able to do in
// a posts_join or posts_where filter by checking if is_search() is true
// With that out of the way, we can construct our queries
$query_posts_page = new WP_Query([
's' => $search,
'paged' => $paged,
'post_type' => ['post', 'page']
]);
$query_woocommerce = new WP_Query([
's' => $search,
'paged' => $paged,
'post_type' => 'product'
]);
?>
<div class="col">
<?php
if ( $query_posts_page->have_posts() ) {
while ( $the_query->have_posts() ) {
$query_posts_page->the_post();
echo get_the_title();
}
/* Restore original Post Data */
wp_reset_postdata();
} else {
echo 'Nope, no more data';
}
?>
</div>
<div class="col">
<?php
if ( $query_woocommerce->have_posts() ) {
while ( $query_woocommerce->have_posts() ) {
$query_posts_page->the_post();
echo get_the_title();
}
/* Restore original Post Data */
wp_reset_postdata();
} else {
echo 'Nope, no more data';
}
?>
</div>
There is however still another problem. we can't automatically generate pagination, considering we are running two custom queries instead of the main query. Furthermore, we are unlikely to have an equal number of normal page/posts and products.
We can figure out what the maximum number of pages is for each of the loops by using max_num_pages
. You can generate something yourself using that.
<?php
$maximum_page = max($query_posts_page->max_num_pages, $query_woocommerce->max_num_pages);
for( $i = 1; $i < $maximum_page; $i++) {
echo "{$i} ";
}
Upvotes: 1