最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Custom search results page query, link permalink to post title while separating by post types

programmeradmin3浏览0评论

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(); ?>

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(); ?>
Share Improve this question edited Aug 17, 2020 at 14:41 user13286 asked Aug 14, 2020 at 22:01 user13286user13286 2272 gold badges12 silver badges29 bronze badges
Add a comment  | 

4 Answers 4

Reset to default 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; 

You can use this to add permalink

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

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; ?>

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);
发布评论

评论列表(0)

  1. 暂无评论