1

I am using Option 3 from this answer as my source. So far it is working great, it is splitting my search results by post type and listing the posts from each post type in their own sections. The only problem is that this solution does not appear to allow for hyperlinking the post titles using the_permalink(); How can I adapt this code so that I can also wrap the post titles in an anchor tag that will direct to the post?

<?php get_header(); ?>
<?php
    $search_query = new WP_Query(
    array(
      'posts_per_page'    => -1,
      's'                 => esc_attr($_GET['s']),
      'post_status'       => 'publish'
    )
);

if ($search_query->have_posts()) : ?>
  <section id="search-results">
    <div class="container">
      <div class="row">
        <div class="col">
          <h2><?php echo $search_query->found_posts.' Search results found'; ?> for: "<?php echo get_search_query(); ?>"</h2>
        </div>
      </div>
      <div 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;
            ?>
            <div class="row">
              <h3>
                <?php
                  $post_type_obj = get_post_type_object($type);
                  echo $post_type_obj->labels->name
                ?>
              </h3>
            </div>
            <div class="row">
              <div class="col">
                <ul>
                <?php foreach($posts_titles[$type] as $title) : ?>
                  <li class="search-item">
                    <a href="PERMALINK SHOULD GO HERE"><?php echo htmlspecialchars($title); ?></a>
                  </li>
                <?php endforeach; ?>
                </ul>
              </div>
            </div>
          <?php endforeach; ?>
        </div>
      </div>  
  </section>

<?php else:
  echo '<div class="search-suggestions-no-results">
          <p>' . __('Sorry, no results found', 'text-domain') . '</p>
        </div>';
endif; ?>
<?php get_footer(); ?>

4 Answers 4

2
+50

I would try a somewhat different approach.

I would move the array of post types to your new WP_Query (since you are working with a limited defined set), and then below where you're looping through each post type in your first foreach statement, I would setup a second query to get all posts found within each $type. If you need to access non-standard postdata (i.e. custom metadata), use global $post, otherwise you don't need it.

That way you can use the_permalink.

Modify your new WP_Query like so:

$search_query = new WP_Query(
array(
  'posts_per_page'    => -1,
  's'                 => esc_attr($_GET['s']),
  'post_status'       => 'publish',
  'post_type'         => array( 'post', 'page', 'glossary' )
  )
);

Then, you can get rid of all the stuff directly below your opening div for your search-results-list and just skip to this:

foreach($types as $type) : 

echo '<ul class="' . $type . '">';
    while( have_posts() ) {
        the_post();
        if( $type == get_post_type() ){ ?>
        
        <div class="entry-content">
<?php if ( has_post_thumbnail() ) { ?>
<a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( esc_html__( 'Permalink to %s', 'quark' ), the_title_attribute( 'echo=0' ) ) ); ?>">
<?php the_post_thumbnail( array(100,100) ); ?>
</a>
<?php } ?>
<?php the_excerpt(); ?>
        
  <?php           
        }   
     rewind_posts();        
    
    echo '</ul>';

endforeach; 
?>

OR Alternatively if you want to keep to WP's newer way of organizing content/templates, you could have a separate template part for each post type with it's own style options, etc.

echo '<ul class="' . $type . '">';
    while( have_posts() ) {
        the_post();
        if( $type == get_post_type() ){
            get_template_part('content', 'search' . $type);
        }   
     rewind_posts();        
    
    echo '</ul>';

endforeach; 
0
0

You can use this to add permalink

echo get_permalink( get_page_by_title( $title, OBJECT, $type ) )
0

Try this:

Replace

$posts_titles[$type][] = get_the_title();

With

$posts_titles[$type][] = array(get_the_title(),get_the_permalink());

And then your foreach outputting the links becomes

<?php foreach($posts_titles[$type] as $link) : ?>
  <li class="search-item">
    <a href="<?php _e($link[1]);?>"><?php echo htmlspecialchars($link[0]); ?></a>
  </li>
<?php endforeach; ?>
0

Replace:

$posts_titles[$type][] = get_the_title();

With:

$posts_titles[$type][get_the_ID()] = get_the_title();

So you will have the post ID in your foreach:

foreach($posts_titles[$type] as $ID => $title)

Finally you can do:

get_permalink($ID);

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.