Jesse
Jesse

Reputation: 239

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;
 ?>

Upvotes: 3

Views: 6789

Answers (3)

Lucano Vera
Lucano Vera

Reputation: 101

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;
}

Upvotes: 4

markd
markd

Reputation: 1526

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).

Upvotes: 2

mrtsherman
mrtsherman

Reputation: 39872

You need to alter the post query to reorder things. You would execute this just before you enter the loop. You can read more about query_posts in the Wordpress codex.

http://codex.wordpress.org/Function_Reference/query_posts

global $wp_query;
$args = array_merge( $wp_query->query, array( 'post_type' => array('type1', 'type2') ) );
query_posts( $args );
//the loop

Upvotes: -1

Related Questions