WordPress搜索-在结果中显示分类术语

时间:2019-07-06 作者:Xav

我有一家定制的邮递式酒店。酒店可以用分类法度假村进行分类。

在我的搜索页面上,我需要能够列出酒店and 结果中的分类术语,作为单独的结果。例如:

Resort Name
Hotel Name
Hotel Name
Hotel Name
度假村应该排在第一位,其次是酒店和其他一切。据我所知,分类术语在WordPress搜索中默认不显示。

在我的功能中。php我目前将搜索限制在特定的帖子类型:

function filter_search($query) {
// Don\'t run in admin area
if(!is_admin()) {
    // Limit search to posts
    if($query->is_main_query() && $query->is_search()) {
        $query->set(\'post_type\', array(\'hotel\', \'post\', \'activities\', \'page\'));
    }

    // Return query
    return $query;
  }
}

add_filter(\'pre_get_posts\', \'filter_search\');
然后在我的搜索中。php我正在按帖子类型对结果进行分组:

<?php $types = array(\'hotel\', \'post\', \'activities\', \'page\');
foreach( $types as $type ){

echo \'<div class="results"> \'; ?>

<?php while( have_posts() ){
  the_post();
  if( $type == get_post_type() ){ ?>

    <div class="result">
      <div class="result-inner">
        <h2>
          <?php if ( $type ==  "hotel"  ) { ?>
            Hotel: 
          <?php } elseif ( $type == "activities" ) { ?>
            Activity: 
          <?php } elseif ( $type == "post" ) { ?>
            Blog Post: 
          <?php } elseif ( $type == "page" ) { ?>
            Page: 
          <?php } else { ?>
            Page: 
          <?php } ?>

          <a href="<?php the_permalink() ?>"><?php the_title(); ?></a>
        </h2>

        <p class="blog-more"><a href="<?php the_permalink() ?>" class="button">View Page</a></p>

        </div>
      </div>
    <?php }
} 
rewind_posts();
echo \'</div> \';
} ?>
我正在努力解决的是如何告诉WordPress在结果中显示分类术语(Resort)作为自己的结果。有人能帮忙吗?

更新:我很乐意保留默认的WordPress搜索顺序。结果不必按分类术语分组。我只需要能够将这个词本身作为一个结果吐出来,并带有该词的链接(并在搜索计数查询中计数)。因此,如果一个搜索匹配了一个分类术语,那么这个分类术语应该排在第一位,然后是其他结果,无论其顺序如何。

4 个回复
最合适的回答,由SO网友:Sally CJ 整理而成

我只需要能够将该术语作为结果本身吐出,并提供该术语的链接(并在搜索计数查询中计数)。因此,如果一个搜索匹配了一个分类术语,那么这个分类术语应该排在第一位,然后是其他结果,无论其顺序如何。

WP_Query::$postsWP_Post 对象,并且不能包含(或与之混合)术语/WP_Term 对象。

然而,有一种方法可以实现您的目标&mdash;使用get_terms() 搜索分类术语并修改WP_Query\'sposts_per_pageoffset 参数,使匹配的术语看起来像是实际搜索结果(即帖子)的一部分。

请注意,目前,get_terms()/WP_Term_Query 仅支持单个搜索关键字&mdash;i、 e。foo, bar 被视为一个关键字&mdash;在里面WP_Query, 这将是两个关键字(foobar).

中的代码/步骤functions.php:

添加此项:

function wpse342309_search_terms( $query, $taxonomy ) {
    $per_page = absint( $query->get( \'posts_per_page\' ) );
    if ( ! $per_page ) {
        $per_page = max( 10, get_option( \'posts_per_page\' ) );
    }

    $paged = max( 1, $query->get( \'paged\' ) );
    $offset = absint( ( $paged - 1 ) * $per_page );
    $args = [
        \'taxonomy\'   => $taxonomy,
//      \'hide_empty\' => \'0\',
        \'search\'     => $query->get( \'s\' ),
        \'number\'     => $per_page,
        \'offset\'     => $offset,
    ];

    $query->terms = [];
    $terms = get_terms( $args );
    if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) {
        $query->terms = $terms;
    }

    $args[\'offset\'] = 0; // always 0
    $args[\'fields\'] = \'count\';
    $query->found_terms = get_terms( $args );

    $query->term_count = count( $query->terms );
    $query->terms_per_page = $per_page; // for WP_Query::$max_num_pages
    $query->is_all_terms = ( (int) $per_page === $query->term_count );

    $query->set( \'posts_per_page\', max( 1, $per_page - $query->term_count ) );
    $query->set( \'offset\', $query->term_count ? 0 :
        max( 0, $offset - $query->found_terms ) );
}
filter_search(), 添加wpse342309_search_terms( $query, \'resort\' ); 此行之后:

$query->set( \'post_type\', array( \'hotel\', \'post\', \'activities\', \'page\' ) );

英寸search.php, 对于主要WordPress查询:

<?php if ( have_posts() ) :

    $total = $wp_query->found_posts + $wp_query->found_terms;
    $wp_query->max_num_pages = ceil( $total / $wp_query->terms_per_page );

    echo \'<div class="results">\';

    // Display terms matching the search query.
    if ( ! empty( $wp_query->terms ) ) {
        global $term; // for use in the template part (below)
        foreach ( $wp_query->terms as $term ) {
            get_template_part( \'template-parts/content\', \'search-term\' );
        }
    }

    // Display posts matching the search query.
    if ( ! $wp_query->is_all_terms ) {
        while ( have_posts() ) {
            the_post();
            get_template_part( \'template-parts/content\', \'search-post\' );
        }
    }

    echo \'</div><!-- .results -->\';

    // Display pagination.
    //the_posts_pagination();
    echo paginate_links( [
        \'total\'   => $wp_query->max_num_pages,
        \'current\' => max( 1, get_query_var( \'paged\' ) ),
    ] );

else :
    echo \'<h1>No Posts Found</h1>\';

endif; // end have_posts()
?>

英寸search.php, 对于自定义WordPress查询:

您应该始终手动调用wpse342309_search_terms().

<?php
$my_query = new WP_Query( [
    \'s\' => \'foo\',
    // ... your args here ...
] );

// Manually apply the terms search.
wpse342309_search_terms( $my_query, \'resort\' );

if ( $my_query->have_posts() ) :

    $total = $my_query->found_posts + $my_query->found_terms;
    $my_query->max_num_pages = ceil( $total / $my_query->terms_per_page );

    echo \'<div class="results">\';

    // Display terms matching the search query.
    if ( ! empty( $my_query->terms ) ) {
        global $term; // for use in the template part (below)
        foreach ( $my_query->terms as $term ) {
            get_template_part( \'template-parts/content\', \'search-term\' );
        }
    }

    // Display posts matching the search query.
    if ( ! $my_query->is_all_terms ) {
        while ( $my_query->have_posts() ) {
            $my_query->the_post();
            get_template_part( \'template-parts/content\', \'search-post\' );
        }
    }

    echo \'</div><!-- .results -->\';

    // Display pagination.
    echo paginate_links( [
        \'total\'   => $my_query->max_num_pages,
        \'current\' => max( 1, get_query_var( \'paged\' ) ),
    ] );

else :
    echo \'<h1>No Posts Found</h1>\';

endif; // end have_posts()
?>

模板第1部分:template-parts/content-search-term.php

<?php global $term;
$term_link = get_term_link( $term, \'resort\' ); ?>

<div class="result">
    <div class="result-inner">
        <h2><a href="<?php echo esc_url( $term_link ); ?>"><?php echo esc_html( $term->name ); ?></a></h2>

        <p class="blog-more"><a href="<?php echo esc_url( $term_link ); ?>" class="button">View Page</a></p>
    </div>
</div>

模板第2部分:template-parts/content-search-post.php

<?php $type = get_post_type(); ?>

<div class="result">
    <div class="result-inner">
        <h2>
            <?php if ( $type ==  "hotel"  ) { ?>
                Hotel:
            <?php } elseif ( $type == "activities" ) { ?>
                Activity:
            <?php } elseif ( $type == "post" ) { ?>
                Blog Post:
            <?php } elseif ( $type == "page" ) { ?>
                Page:
            <?php } else { ?>
                Page:
            <?php } ?>

            <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
        </h2>

        <p class="blog-more"><a href="<?php the_permalink(); ?>" class="button">View Page</a></p>
    </div>
</div>

SO网友:Sally CJ

如果您想要这样的显示:

Hotels: Resort 1 <- "Resort 1" is a term in the "resort" taxonomy
  Sample Hotel
  Sample Hotel 2
  Sample Hotel 4 <- This post is assigned to both "Resort 1" and "Resort 2"

Hotels: Resort 2 <- "Resort 2" is a term in the "resort" taxonomy
  Sample Hotel 3
  Sample Hotel 4 <- This post is assigned to both "Resort 1" and "Resort 2"

Blog Posts
  Sample Post
  Sample Post 2

Activities
  Sample Activity
  Sample Activity 2

Pages
  Sample Page
然后这可以给你一个答案,我们首先根据帖子类型或“酒店”帖子的“度假村”术语名称对帖子进行分组:(这在里面search.php)

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

    <div class="results">

        <?php
        $_posts = $wp_query->posts;
        $posts_arr = [];
        $resorts = [];

        foreach ( $_posts as $i => $p ) {
            // Group "hotel" posts by the "resort" term name.
            if ( \'hotel\' === $p->post_type ) {
                $terms = get_the_terms( $p, \'resort\' );
                if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) {
                    foreach ( $terms as $term ) {
                        if ( ! isset( $resorts[ $term->name ] ) ) {
                            $resorts[ $term->name ] = [];
                        }
                        $resorts[ $term->name ][] =& $_posts[ $i ];
                    }
                }
            // Group other posts by their type.
            } else {
                if ( ! isset( $posts_arr[ $p->post_type ] ) ) {
                    $posts_arr[ $p->post_type ] = [];
                }
                $posts_arr[ $p->post_type ][] =& $_posts[ $i ];
            }
        }
        $posts_arr[\'hotel\'] = ! empty( $resorts );

        // List of post_type => Heading.
        $types = [
            \'hotel\'      => \'Hotels\',
            \'post\'       => \'Blog Posts\',
            \'activities\' => \'Activities\',
            \'page\'       => \'Pages\',
        ];

        foreach ( $types as $type => $heading ) {
            if ( ! isset( $posts_arr[ $type ] ) ) {
                continue;
            }

            // Display "hotel" posts.
            if ( \'hotel\' === $type ) {
                foreach ( $resorts as $name => $ps ) {
                    echo \'<h2>Hotels: \' . $name . \'</h2>\';
                    foreach ( $ps as $post ) {
                        setup_postdata( $post );
                        get_template_part( \'template-parts/content\', \'search\' );
                    }
                }
            // Display posts in other post types.
            } else {
                echo \'<h2>\' . $heading . \'</h2>\';
                foreach ( $posts_arr[ $type ] as $post ) {
                    setup_postdata( $post );
                    get_template_part( \'template-parts/content\', \'search\' );
                }
            }
        }

        unset( $_posts, $posts_arr, $resorts );
        ?>

    </div><!-- .results -->

<?php endif; // end have_posts() ?>
和模板部分(content-search.php 在…内wp-content/themes/your-theme/template-parts):

<div <?php post_class( \'result\' ); ?>>
    <div class="result-inner">
        <h4><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h4>
        <p class="blog-more"><a href="<?php the_permalink(); ?>" class="button">View Page</a></p>
    </div>
</div>

SO网友:HU ist Sebastian

如果您想按自定义分类法对搜索结果进行分组,您可以像Sally CJ建议的那样在查询后对帖子进行分组,但只有当您的所有搜索结果都在一个页面上时,这才能正常工作。

要对搜索结果进行排序并使用分页,您必须更改MySQL查询,所以这就是我们要做的。

步骤1:在pre\\u get\\u posts操作中向“posts\\u子句”添加筛选器以更改生成的查询:

add_action(\'pre_get_posts\',\'setup_my_query_interception\');

function setup_my_query_interception($query){
    if(!is_admin() && $query->is_search() && $query->is_main_query()){
     add_filter( \'posts_clauses\', \'order_by_taxonomy_intercept_query_clauses\', 20, 1 );
  }
}
步骤2:在order\\u by\\u taxonomy\\u intercept\\u query\\u子句功能中,增强查询:

function order_by_taxonomy_intercept_query_clauses($pieces){
        global $wpdb;
        //First we add the taxonomy and term tables to our joins...
        $pieces[\'join\'].=" LEFT JOIN $wpdb->term_relationships trt ON ($wpdb->posts.ID = trt.object_id) LEFT JOIN $wpdb->term_taxonomy ttt ON (trt.term_taxonomy_id = ttt.term_taxonomy_id) INNER JOIN $wpdb->terms termts ON (termts.term_id = ttt.term_id)";
        //Now we add a WHERE condition that we only want Resort Terms
        $pieces[\'where\'].=" AND ttt.taxonomy = \'resort\'"; //change this, if your taxonomy type is named different
        //At last, we tell the orderby to FIRST order by the term title, after that use the wanted orderby
        $pieces[\'orderby\']="termts.name ASC, ".$pieces[\'orderby\'];
        //Remove the filter so it only runs once in our main query
        remove_filter(\'posts_clauses\', \'order_by_taxonomy_intercept_query_clauses\');
        return $pieces;
}
第三步:您的搜索结果现在将首先由度假村订购。如果您想在搜索结果之前回显度假村名称,您必须在搜索中执行类似操作。php或索引。php:

循环之前:

if(is_search()){
    global $activetax;
    $activetax = "";
    echo \'<div class="mywrapper">
}
在循环中:

if(is_search()){
$resorts = get_the_terms(get_the_ID(),\'resort\');
if(is_array($resorts)){
    if(!($activetax==$resorts[0]->name)){
            $activetax = $resorts[0]->name;
            ?>
            </div>
            <h2 id="tax_id_<?php echo $resorts[0]->term_id; ?>" class="resort-header"><?php echo $activetax; ?></h2>
            <div class="mywrapper">
            <?php
    }
}
}
get_template_part(\'content\'); 
循环后:

if(is_search()){
 echo "</div>";
}
没有测试它,但它应该可以工作。

快乐的编码!

SO网友:Jesse Nickles

ChandanKumar在his blog post (2019年1月)组合多个查询,清理它们,然后显示组合结果:

删除搜索中的旧查询。php文件使用wp\\u query,使用这些匹配的ID查询所有帖子(通过税务查询)。然后将生成的post\\u id存储在一个数组中他的代码中没有提到许可证,但他似乎在公开分享:

<div class="page-description"><?php echo get_search_query(); ?></div>
<?php
$search=get_search_query();
$all_categories = get_terms( array(\'taxonomy\' => \'category\',\'hide_empty\' => true) ); 
$all_tags = get_terms( array(\'taxonomy\' => \'post_tag\',\'hide_empty\' => true) );
//if you have any custom taxonomy
$all_custom_taxonomy = get_terms( array(\'taxonomy\' => \'your-taxonomy-slug\',\'hide_empty\' => true) );

$mcat=array();
$mtag=array();
$mcustom_taxonomy=array();

foreach($all_categories as $all){
$par=$all->name;
if (strpos($par, $search) !== false) {
array_push($mcat,$all->term_id);
}
}

foreach($all_tags as $all){
$par=$all->name;
if (strpos($par, $search) !== false) {
array_push($mtag,$all->term_id);
}
}

foreach($all_custom_taxonomy as $all){
$par=$all->name;
if (strpos($par, $search) !== false) {
array_push($mcustom_taxonomy,$all->term_id);
}
}

$matched_posts=array();
$args1= array( 
\'post_status\' => \'publish\',
\'posts_per_page\' => -1,
\'tax_query\' => array(
\'relation\' => \'OR\',
array(
\'taxonomy\' => \'category\',
\'field\' => \'term_id\',
\'terms\' => $mcat
),
array(
\'taxonomy\' => \'post_tag\',
\'field\' => \'term_id\',
\'terms\' => $mtag
),
array(
\'taxonomy\' => \'custom_taxonomy\',
\'field\' => \'term_id\',
\'terms\' => $mcustom_taxonomy
)
)
);

$the_query = new WP_Query( $args1 );
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
array_push($matched_posts,get_the_id());
//echo \'<li>\' . get_the_id() . \'</li>\';
}
wp_reset_postdata();
} else {

}

?>
<?php
// now we will do the normal wordpress search
$query2 = new WP_Query( array( \'s\' => $search,\'posts_per_page\' => -1 ) );
if ( $query2->have_posts() ) {
while ( $query2->have_posts() ) {
$query2->the_post();
array_push($matched_posts,get_the_id());
}
wp_reset_postdata();
} else {

}
$matched_posts= array_unique($matched_posts);
$matched_posts=array_values(array_filter($matched_posts));
//print_r($matched_posts);
?>

<?php
$paged = ( get_query_var(\'paged\') ) ? get_query_var(\'paged\') : 1;
$query3 = new WP_Query( array( \'post_type\'=>\'any\',\'post__in\' => $matched_posts ,\'paged\' => $paged) );
if ( $query3->have_posts() ) {
while ( $query3->have_posts() ) {
$query3->the_post();
get_template_part( \'template-parts/content/content\', \'excerpt\' );
}
twentynineteen_the_posts_navigation();
wp_reset_postdata();
} else {

}
?>

相关推荐

Slow Query On Search

请注意,我在wordpress搜索中有一个非常慢的查询,使用SHOW FULL PROCESSLIST; 下面是一个查询示例SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND (((wp_posts.post_title LIKE \'%Industreet%\') OR (wp_posts.post_excerpt LIKE \'%Industreet%\') OR (wp_posts.post_content LI