9

My site has 3 unique post types:

  • Default Blog posts ("post")
  • custom type "lesson"
  • custom type "series"

When the user searches the site, I would like pertinent results from all 3 post types to show up on the search results page. The "posts" results are in one container, "lesson" results in a separate container, etc. How can I modify the search page to accomplish this?

Here is my current loop:

<?php get_header(); ?>
<div class="row">
    <div class="small-12 large-8 columns" role="main">

        <?php do_action('foundationPress_before_content'); ?>

        <h2><?php _e('Search Results for', 'FoundationPress'); ?> "<?php echo get_search_query(); ?>"</h2>

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

        <?php while ( have_posts() ) : the_post(); ?>
            <?php if( get_post_type() == 'lesson' ) {
                    get_template_part('content', 'lesson');
                } else if ( get_post_type() == 'post' ) {
                    get_template_part('content', get_post_format());
                }
            ?>
        <?php endwhile; ?>

        <?php else : ?>
            <?php get_template_part( 'content', 'none' ); ?>

    <?php endif;?>

    <?php do_action('foundationPress_before_pagination'); ?>

    <?php if ( function_exists('FoundationPress_pagination') ) { FoundationPress_pagination(); } else if ( is_paged() ) { ?>

        <nav id="post-nav">
            <div class="post-previous"><?php next_posts_link( __( '&larr; Older posts', 'FoundationPress' ) ); ?></div>
            <div class="post-next"><?php previous_posts_link( __( 'Newer posts &rarr;', 'FoundationPress' ) ); ?></div>
        </nav>
    <?php } ?>

    <?php do_action('foundationPress_after_content'); ?>

    </div>
    <?php get_sidebar(); ?>

<?php get_footer(); ?>
2
  • Don't use elseif, use only if. This way, all the templates will be displayed.
    – Ciprian
    Commented Mar 20, 2015 at 16:52
  • I don't think if vs. elseif will make a difference here.
    – s_ha_dum
    Commented Mar 25, 2015 at 16:04

1 Answer 1

21

You can run the same loop multiple times by using rewind_posts() to output each type separately.

if( have_posts() ){
    $types = array('post', 'lesson', 'series');
    foreach( $types as $type ){
        echo 'your container opens here for ' . $type;
        while( have_posts() ){
            the_post();
            if( $type == get_post_type() ){
                get_template_part('content', $type);
            }
        }
        rewind_posts();
        echo 'your container closes here for ' . $type;
    }
}
8
  • 1
    Hi -- the problem is I need to store each post type into its own container (I'm using a tabbed interface, so if they hit the "lesson" tab they get all the "lesson" videos that match their search, etc.) Not sure how to adapt your method to that
    – tdc
    Commented Mar 21, 2015 at 1:01
  • 1
    yes, that's what I assumed, and that's what this example is for. you put whatever container markup you want between the foreach and the while loops.
    – Milo
    Commented Mar 21, 2015 at 1:54
  • 1
    Ah I see with the edited post, thanks. Do you know if this will work properly with pagination as well?
    – tdc
    Commented Mar 23, 2015 at 13:55
  • 2
    this will just sort posts on a per-page basis, and pagination will work the same as without this code. if the goal is to sort the posts together across all pages, you'll have to alter the query directly with a filter.
    – Milo
    Commented Mar 23, 2015 at 15:36
  • 1
    That's more in line with what I'm trying to do. Basically I just need a clean way for people to sort through search results by post type. Optimally I wouldn't even bother with pagination and just have all matching results spit out into each container but I'm not sure how heavy an impact that could have on site performance
    – tdc
    Commented Mar 23, 2015 at 15:41

Not the answer you're looking for? Browse other questions tagged or ask your own question.