To avoid types with no results you can e.g.
- one additional time go through the loop and count the occurrences of each type, the number of returned results is not large (only 10 per page)
- display the type title when you encounter the first post with the given type (move to inside
while
loop, I know, less readable code) - go through the loop one time and collect post titles to the table divided into types
First option
<ul class="search-results-list">
<?php
$types = array( 'post', 'page', 'glossary' );
$occurrences = [];
while( $search_query->have_posts() )
{
$search_query->next_post();
$type = $search_query->post->post_type;
if ( !isset($occurrences[$type]) )
$occurrences[$type] = 1;
else
$occurrences[$type] += 1;
}
rewind_posts();
foreach( $types as $type ) :
if ( !isset($occurrences[$type]) )
continue;
?>
<li class="search-results-post-type-item post-type-<?php echo $type ?>">
//
// remaining code
//
</li>
<?php endforeach; ?>
</ul>
Second option
$types = array( 'post', 'page', 'glossary' );
foreach( $types as $type ) :
$type_header_printed = false;
?>
<?php
while( $search_query->have_posts() ):
$search_query->the_post();
if( $type == get_post_type() ) :
// -- post type header -----
if ( !$type_header_printed ) :
$type_header_printed = true;
?>
<li class="search-results-post-type-item post-type-<?php echo $type ?>">
<header class="post-type-header">
<h5 class="post-type-title">
<?php
$post_type_obj = get_post_type_object( $type );
echo $post_type_obj->labels->name
?>
</h5>
</header>
<ul class="search-results-list">
<?php // -- header end -----
endif; ?>
<li class="search-results-list-item">
<h4 class="entry-title"><?php the_title();?></h4>
</li>
<?php
endif;
endwhile;
rewind_posts();
if ( $type_header_printed ) : ?>
</ul>
</li>
<?php endif; ?>
<?php endforeach; ?>
Third option
<ul class="search-results-list">
<?php
$types = array( 'post', 'page', 'glossary' );
$posts_titles = [];
while( $search_query->have_posts() )
{
$search_query->the_post();
$type = $search_query->post->post_type;
if ( !isset($posts_titles[$type]) )
$posts_titles[$type] = [];
$posts_titles[$type][] = get_the_title();
}
rewind_posts();
foreach( $types as $type ) :
if ( !isset($posts_titles[$type]) )
continue;
?>
<li class="search-results-post-type-item post-type-<?php echo $type ?>">
<header class="post-type-header">
<h5 class="post-type-title">
<?php
$post_type_obj = get_post_type_object( $type );
echo $post_type_obj->labels->name
?>
</h5>
</header>
<ul class="search-results-list">
<?php foreach( $posts_titles[$type] as $title ) : ?>
<li class="search-results-list-item">
<h4 class="entry-title"><?php echo htmlspecialchars($title); ?></h4>
</li>
<?php endforeach; ?>
</ul>
</li>
<?php endforeach; ?>
</ul>