Seperating Custom Post Search Results

I have a site that has a few custom post types. When a customer searches it shows a combination of all the different posts. I’d like to segment the two on the same page resulting in something that looks like the example below. Any help would be appreciated.

Showing results for: really cool search
Video Management
from a central location. Radius offers
interactive map capability, and
multiple monitor support. Designed for
a multiple monitor environmen…
http://openeye.net/products/software/video-management


Knowledge Base Entries:
Repairing your device
from a central location. Radius offers
interactive map capability, and
multiple monitor support. Designed for
a multiple monitor environmen…
http://openeye.net/?faq=video-management-repair

Example of my loop from loop-search.php

<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<h4 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php printf( esc_attr__( 'Permalink to %s', 'twentyten' ), the_title_attribute( 'echo=0' ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h4>
<?php if ( is_archive() || is_search() ) : // Only display excerpts for archives and search. ?>
    <div class="entry-summary">
        <?php the_post_thumbnail; ?>
        <?php if (function_exists('relevanssi_the_excerpt')) { relevanssi_the_excerpt(); }; ?>
        <a href="<?php the_permalink(); ?>"><?php the_permalink(); ?></a>
    </div><!-- .entry-summary -->
<?php else : ?>
    <div class="entry-content">
        <?php the_post_thumbnail; ?>
        <?php the_content( __( 'Continue reading', 'twentyten' ) ); ?>
        <?php wp_link_pages( array( 'before' => '<div class="page-link">' . __( 'Pages:', 'twentyten' ), 'after' => '</div>' ) ); ?>
        <a href="<?php the_permalink(); ?>"><?php the_permalink(); ?></a>
    </div><!-- .entry-content -->
<?php endif; ?>

my changes to search.php

<?php if ( have_posts() ) : $posts_per_page = 20; ?>
    <span style="font-size:18px;" class="page-title"><?php printf( __( 'Showing results for: %s', 'twentyten' ), '<span>' . get_search_query() . '</span>' ); ?></span>
    <?php
    /* Run the loop for the search to output the results.
     * If you want to overload this in a child theme then include a file
     * called loop-search.php and that will be used instead.
     */
     get_template_part( 'loop', 'search' );
    ?>
<?php else : ?>
    <div id="post-0" class="post no-results not-found">
        <h2 class="entry-title"><?php _e( 'Nothing Found', 'twentyten' ); ?></h2>
        <div class="entry-content">
    <?php if (function_exists('relevanssi_didyoumean')) {
        relevanssi_didyoumean(get_search_query(), "<p>Sorry, but nothing matched your search criteria. Please try again with some different keywords. Or you can also try ", "</p>", 5);
    }?>
            <?php related_searches(); ?>
        </div><!-- .entry-content -->
    </div><!-- #post-0 -->
<?php endif; ?>

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You can group posts by type using posts_groupby filter hook:

add_filter('posts_groupby', 'group_by_post_type' );
function group_by_post_type( $groupby )
{
  global $wpdb;
  if( !is_search() ) {
    return $groupby;
  }
  $mygroupby = "{$wpdb->posts}.post_type";
  if( !strlen(trim($groupby))) {
    // groupby was empty, use ours
    return $mygroupby;
  }
  // wasn't empty, append ours
  return $groupby . ", " . $mygroupby;
}

Then in your loop of do something like this:

$last_type="";
$typecount = 0;
while (have_posts()){
    the_post();
    if ($last_type != $post->post_type){
        $typecount = $typecount + 1;
        if ($typecount > 1){
            echo '</div>'; //close type container
        }
        // save the post type.
        $last_type = $post->post_type;
        //open type container
        switch ($post->post_type) {
            case 'post':
                echo "<div class="post container"><h2>posts search result</h2>";
                break;
            case 'page':
                echo "<div class="page container"><h2>pages search result</h2>";
                break;
            case 'custom_type_name':
                echo "<div class="custom container"><h2>custom post type search result</h2>";
                break;
            //add as many as you need.
        }
    }

    //...
    // do your loop 
    //...
}

Method 2

Just wanted to add that while @bainternet’s up-voted solution is great, it can break the Media Library’s search function. This problem, and a simple solution, both appear here.

The simple solution is to add this conditional around the code above:

if (!is_admin()) {
  [your code here]
}

Method 3

I got this working after tweaking the above solution a bit. First the filter need to be changed to retrieve more that 1 result:

add_filter('posts_orderby', 'group_by_post_type', 10, 2);
function group_by_post_type($orderby, $query) {
global $wpdb;
if ($query->is_search) {
    return $wpdb->posts . '.post_type DESC';
}
// provide a default fallback return if the above condition is not true
return $orderby;
}

Then the loop needed to be tweaked a little. I wanted to style my results differently with different information, so I added a further conditional.

<?php if(have_posts()) : ?>

<?php   
$last_type="";
$typecount = 0;
while (have_posts()) :
the_post();
if ($last_type != $post->post_type){
    $typecount = $typecount + 1;
    if ($typecount > 1){
        echo '</div><!-- close container -->'; //close type container
    }
    // save the post type.
    $last_type = $post->post_type;
    //open type container
    switch ($post->post_type) {
        case 'post':
            echo "<div class="postsearch container"><h2>Blog Results</h2>";
            break;
        case 'product':
            echo "<div class="productsearch container"><h2>Product Search   Results</h2>";
            break;

    }
} 
?>

    <?php if('post' == get_post_type()) : ?>
     <li class="post"><?php the_title(); ?></li>
<?php endif; ?>

  <?php if('product' == get_post_type()) : ?>
 <li class="product"><?php the_title(); ?></li>
  <?php endif; ?>


<?php endwhile; ?>

<?php else : ?>
<div class="open-a-div">
<p>No results found.</p>    

<?php endif; ?>       

</div><!-- throw a closing div in -->

Basically the only changes are the filter and the closing div that was omitted at the end. That and the “No results found.” This is working on my site.


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

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x