按帖子类型分隔搜索结果

时间:2015-07-08 作者:semibur

原始问题:Seperating Custom Post Search Results

我试图在我的网站上实现这段代码,但我遇到了一些问题。我所做的更改是,我为第三个帖子类型添加了另一个开关,如下所示:

<?php if (have_posts()) : ?>
    <?php
    $last_type = "";
    $typecount = 0;
    while (have_posts()) :
        the_post();
        if ($last_type != $post->post_type) {
            $typecount = $typecount + 1;
            if ($typecount > 1) {
                echo \'</div><!-- close container -->\'; //close type container
            }
            // save the post type.
            $last_type = $post->post_type;
            //open type container
            switch ($post->post_type) {
                case \'post\':
                    echo "<div class=\\"postsearch container\\"><h2>Blog Results</h2>";
                    break;
                case \'partner\':
                    echo "<div class=\\"partnersearch container\\"><h2>Partner Search Results</h2>";
                    break;
                case \'fiches_pratiques\':
                    echo "<div class=\\"lessonsearch container\\"><h2>lesson Search Results</h2>";
                    break;
            }
        }
        ?>

        <?php if (\'post\' == get_post_type()) : ?>
            <li class="post"><?php the_title(); ?></li>
        <?php endif; ?>

        <?php if (\'partner\' == get_post_type()) : ?>
            <li class="partner"><?php the_title(); ?></li>
        <?php endif; ?>

        <?php if (\'lesson\' == get_post_type()) : ?>
            <li class="lesson"><?php the_title(); ?></li>
        <?php endif; ?>


    <?php endwhile; ?>

<?php else : ?>
    <div class="open-a-div">
        <p>No results found.</p>    

    <?php endif; ?>       
此代码导致以下结果:

Lessons Search Results

第1课第4课第3课

Blog Results

测试接头

Partner Search Results

第四合伙人

Blog Results

Lorem ipsum Wave 2.0 Web和;科技云开放容器项目

正如你所注意到的,博客结果部分翻了一番。对可能出现的问题有什么建议吗?

已安装的搜索插件:Relevanssi

NOTE: 没有Relevanssi(但有Search Everything插件),它会以适当的方式显示,但Search Everything插件不允许多词搜索,这在我的情况下是必须的。

最新Wordpress版本。

提前谢谢你。

3 个回复
最合适的回答,由SO网友:Pieter Goosen 整理而成

这里有一个想法,在循环执行之前对其进行排序。您当前的问题就是这个。您将看到,排序类型(如果我正确,我认为您的顺序不是按文章类型的字母顺序)在本机上是不可能的,因此我们需要解决方法(即使您只需要按字母顺序排序的文章类型,本机方法仍然缺乏适当的功能)。这就是usort() 进来后,我们可以按我们想要的任何顺序对帖子类型进行排序。这将在the_posts 滤器

我可以给你们两个例子。NOTE: 代码示例至少需要PHP 5.4+,这应该是您现在的最低版本。5.4之前的所有版本都已过期,不受支持,因此,如果您仍在使用这些版本,则存在巨大的安全风险。

按自定义邮件类型顺序排序

add_filter( \'the_posts\', function( $posts, $q ) 
{
    if( $q->is_main_query() && $q->is_search() ) 
    {
        usort( $posts, function( $a, $b ){
            /**
             * Sort by post type. If the post type between two posts are the same
             * sort by post date. Make sure you change your post types according to 
             * your specific post types. This is my post types on my test site
             */
            $post_types = [
                \'event_type\' => 1,
                \'post\'       => 2,
                \'cameras\'    => 3
            ];              
            if ( $post_types[$a->post_type] != $post_types[$b->post_type] ) {
                return $post_types[$a->post_type] - $post_types[$b->post_type];
            } else {
                return $a->post_date < $b->post_date; // Change to > if you need oldest posts first
            }
        });
    }
    return $posts;
}, 10, 2 );
按帖子类型字母顺序排序
add_filter( \'the_posts\', function( $posts, $q ) 
{
    if( $q->is_main_query() && $q->is_search() ) 
    {
        usort( $posts, function( $a, $b ){
            /**
             * Sort by post type. If the post type between two posts are the same
             * sort by post date. Be sure to change this accordingly
             */

            if ( $a->post_type != $b->post_type ) {
                return strcasecmp( 
                    $a->post_type, // Change these two values around to sort descending
                    $b->post_type 
                );
            } else {
                return $a->post_date < $b->post_date; // Change to > if you need oldest posts first
            }
        });
    }
    return $posts;
}, 10, 2 );
现在,如果您没有使用自定义查询代替主查询,您的帖子应该在搜索页面上按帖子类型排序。对于上面的代码,请保持原样,无需对其进行任何调整

SO网友:s_ha_dum

您正在按照Relevanssi插件认为正确的顺序获取帖子结果。也就是说,根据插件的逻辑(我不知道确切的逻辑是什么),您将以最相关的顺序获得结果,这就是插件的要点。

一般来说,按职位类型排序并不难:

function orderby_type($orderby) {
  remove_filter(\'posts_orderby\',\'orderby_type\');
  global $wpdb;
  return $wpdb->posts.\'.post_type\';
}
add_filter(\'posts_orderby\',\'orderby_type\');
$args = array(
  \'post_type\' => array(\'post\',\'page\',\'book\'),
  \'orderby\' => \'post_type\'
);
$w = new WP_Query($args);
然而,我希望这会打破插件提供的“相关”排序。事实上,你所做的任何事情都可能在某种程度上打破“相关性”的计算。以下内容应该是您所能做的最好的事情:

function resort_posts($posts) {
  $sorted = $ret = array();
  foreach ($posts as $p) {
    $sorted[$p->post_type][] = $p;
  }
  foreach ($sorted as $s) {
    $ret = array_merge($ret,$s);
  }
  // verify
//   $pid = wp_list_pluck($posts,\'ID\');
//   $sid = wp_list_pluck($ret,\'ID\');
//   var_dump(array_diff($pid,$sid));
  return $ret;
}
add_filter(\'the_posts\',\'resort_posts\');
您需要弄清楚如何使用Relevansi来实现这一点,而不必同时处理网站上的所有查询(它将按书面形式执行)。我从来没有使用过那个插件,所以我不能说(顺便说一下,特定于插件的问题也是离题的)

SO网友:Nicolai Grossherr

你搜索过endless expanses of the internet ?

因为SERP上的第一个条目是relvanssi知识库中的一篇文章,标题为»Separating posts by post type«,听起来很适合我。以下是拟议方法的代码:

add_filter(\'relevanssi_hits_filter\', \'separate_result_types\');
function separate_result_types($hits) {
    $types = array();

    // Split the post types in array $types
    if (!empty($hits)) {
        foreach ($hits[0] as $hit) {
            if (!is_array($types[$hit->post_type])) $types[$hit->post_type] = array();                        
            array_push($types[$hit->post_type], $hit);
        }
    }

    // Merge back to $hits in the desired order
    $hits[0] = array_merge(
        $types[\'mycustomtypethatgoesfirst\'], 
        $types[\'thesecondmostimportanttype\'], 
        $types[\'post\'], $types[\'pages\']
    );
    return $hits;
}
注释:

我什么都没做,只是复制了代码

结束

相关推荐

Search query with Ajax

我正在运行一个$wpdb 选择查询并从文本框中获取其参数。结果显示只要我按下搜索按钮,但我想用Ajax做同样的事情,而不刷新页面。我什么都试过了,但页面仍在刷新。jQuery代码:jQuery(document).ready(function() { jQuery(\"#Submityourskill\").click(function(){ jQuery.post(yes.ajaxurl,{action : \'doit\'},