wordpress group by post type on search page

I would like to display search results grouped by post type. I have regular posts, pages,
and a custom post type of product. How would I accomplish this by editing the below code.
The code below just shows all posts and pages right now.

<?php
 while (have_posts()) : the_post();  
 echo "<h1>";
 echo $post->post_type;
 echo $post->post_title;
 echo "</h1>";
 endwhile;
 ?>

Related posts

Leave a Reply

3 comments

  1. This code alters the original search query to order the results by post-type in the order you select. There are other solutions, but this is the only one i found that doesn’t break pagination or requires multiple queries.

    add_filter('posts_orderby', 'my_custom_orderby', 10, 2);
    
    function my_custom_orderby($orderby_statement, $object) {
      global $wpdb;
    
      if (!is_search())
        return $orderby_statement;
    
      // Disable this filter for future queries (only use this filter for the main query in a search page)
      remove_filter(current_filter(), __FUNCTION__);
    
      $orderby_statement = "FIELD(".$wpdb - > prefix.
      "posts.post_type, 'post-type-c', 'post-type-example-a', 'custom-post-type-b') ASC";
    
      return $orderby_statement;
    }
    
  2. In your case, I’d do two things:

    1. filter the search page’s initial query to a particular post type
    2. use one WP_Query call for each remaining post type

    For (1), this would go in your functions.php:

    <?php
    function SearchFilter($query) {
        if ($query->is_search && !is_admin()) {
            if (isset($query->query["post_type"])) {
                $query->set('post_type', $query->query["post_type"]);
            } else {
                $query->set('post_type', 'product');
            }
        }
        return $query;
    }
    add_filter('pre_get_posts','SearchFilter');
    ?>
    

    For (2), adapt the code you provided from your template file:

    <?php
    $s = isset($_GET["s"]) ? $_GET["s"] : "";
    $posts = new WP_Query("s=$s&post_type=post");
    if ( $posts->have_posts() ) :
        while ( $posts->have_posts() ) : $posts->the_post();
            echo "<h1>";
            echo $post->post_type;
            echo $post->post_title;
            echo "</h1>";
        endwhile;
        wp_reset_postdata();
    endif;
    ?>
    

    You can re-use this code for each other post type.

    It’s best to avoid using query_posts… see querying posts without query_posts (even WordPress devs agree).