1

I want to group my search results to post types. I was able to do it by using foreach with an array of post types that I want but it also displays the ones that doesn't have any results. Here's my code taken from another thread.

<?php 
    if( have_posts() ){
        $types = array('post', 'videos', 'graphics', 'photos');
        foreach( $types as $type ){?>
            <div class="card">
                <div class="card-header">
                    <h4><?=$type;?></h4>
                </div>
                
                <div class="card-body">
    <div class="type-<?=$type;?> row row-cols-1 row-cols-sm-1 row-cols-md-2 row-cols-lg-3 row-cols-xl-3">
        <?php
            while( have_posts() ){
                the_post();
                if( $type == get_post_type() ){
                    echo get_template_part('template-part/content', $type);
                }
            }
            rewind_posts();
        ?>
            </div>
        </div>
    </div>

        <?php
        }
    }
?>

Right now, it displays as:

Post

  1. post 1
  2. post 2

Graphics

Videos

  1. Videos 1
  2. Videos 2

Photos

How can I remove the Graphics, Photos in the header if graphics and photos type doesn't have anything to show?

4
  • You've got a few options: 1) don't emit the card-header until you find the first post in that category, and ditto don't emit the close div unless you need it; 2) group all of the posts together ahead of time, either in code or in SQL, then emit the groups. I don't know how efficient either of these are going to be though, or how efficient the rewind is, but I'd guess it's OK as WordPress caches posts loaded for the current page.
    – Rup
    Commented Aug 25, 2021 at 11:10
  • @Rup - I made an answer with the first option. The second option seems doable to but I find the first one more direct and easy. Thanks! Commented Aug 26, 2021 at 2:48
  • @Rup - my answer was incorrect since if I have multiple results, the card-header and the ending div also repeats. So I still have no answer. Commented Aug 26, 2021 at 4:18
  • For the first way you'd need a flag to say if this was the first one in that category or not that you set to true at the start of the foreach( $types as $type ){?> loop. When you have a post, if $first == true then emit the card-header and set $first = false. At the end of the loop if $first == false then we have had posts in this category so generate the close div.
    – Rup
    Commented Aug 26, 2021 at 8:52

1 Answer 1

2

The only way is to count them or (re)request them via WP_Query. I think I prefer the first solution because it's the less complex.

<?php if (have_posts()) : ?>
    <?php
    // We change the definition of the array to be able to store the count of each post_type
    $types = array('post' => 0, 'videos' => 0, 'graphics' => 0, 'photos' => 0);
    while (have_posts()) {
        the_post();
        // We check that only allowed post_type are counted
        if (array_key_exists(get_post_type(), $types)) {
            $types[get_post_type()]++;
        }
    }
    ?>
    <?php foreach ($types AS $type => $nb_of_type) : ?>
        <?php // We only show post_types that have at least one result  ?>
        <?php if ($nb_of_type > 0) : ?>
            <div class="card">
                <div class="card-header">
                    <h4><?= $type; ?></h4>
                </div>

                <div class="card-body">
                    <?php while (have_posts()) : the_post(); ?>
                        <?php if (get_post_type() === $type) : ?>
                            <?php get_template_part('template-part/content', $type); ?>
                        <?php endif; ?>
                    <?php endwhile; ?>
                </div>
            </div>
        <?php endif; ?>
    <?php endforeach; ?>
<?php endif; ?>
1
  • This one works very well. I have to add 'attachments' to the array of $types so that it also displays attachments. Thanks! Commented Aug 26, 2021 at 10:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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