显示类别中的所有帖子,并在顶部显示特定的标签帖子

时间:2014-09-16 作者:PreeT

Rephrase question

我需要为我的类别在循环中订购帖子car. 如果我访问car, 我需要标记所有帖子BMW 首先显示,然后显示未使用标记标记的其他帖子BMW

如果我的posts_per_page 设置为显示10篇文章,我在第一页,十篇文章中有三篇被标记BMW, 然后这三个帖子必须首先出现,其余的紧跟在这三个帖子之后。当我点击并转到第二页时,同样的情况也适用。如果我在这10篇帖子中有5篇贴了标签BMW, 同样,它们必须先出现在其他5个帖子之前。

这可能吗?

3 个回复
SO网友:birgire

以下是通过使用loop_start 挂钩:

add_action( \'loop_start\', function( $q ) {
    if( $q->is_main_query() && $q->is_category( \'car\' ) )
        usort( $q->posts, function( $a, $b ){
            return -1 * has_tag( \'bmw\', $a ) + 1 * has_tag( \'bmw\', $b );            });
}, 10, 2 );
我们也可以使用相同的方法the_posts 滤器

Update:

要按第一个类别名称对主页上的帖子进行排序,我们可以尝试以下操作,例如:

add_action( \'loop_start\', function( $q ) {
    if( $q->is_main_query() && $q->is_home() )
        usort( $q->posts, function( $a, $b ){
            return strcasecmp( 
                get_the_category( $a->ID )[0]->name, 
                get_the_category( $b->ID )[0]->name 
            );
        });
}, 10, 2 );
我们使用的位置strcasecmp 用于不区分大小写的字符串比较。

SO网友:Pieter Goosen

不能在循环内进行这种类型的排序。但是,您可以通过编写自己的函数来完成

这是我的解决方案:PS!需要PHP 5.4+

STEP 1

创建一个名为wpse161553_loop_sort($tag=\'\'). 这将在主查询中使用单个标记。

STEP 2

您需要从主查询中获取post对象。它们已经可用,可以通过访问$wp_query->posts;. (有关可用对象的完整列表以及如何访问它们,请参见WP_Post).

STEP 3

创建并启动新计数器。此计数器将用于从$wp_query->posts; 过后

STEP 4

获取posts_per_page 在后端设置选项。该值将添加到所有没有所需标签的帖子的计数器中。这将使所有这些帖子超过所需的标签帖子

STEP 5

在循环内部,使用has_tag() 对照所需标签检查每个帖子。如果post具有所需的标记,请将当前计数器值推送到数组中($c) 按原样。如果贴子没有所需的标记,则按下当前计数器的值加上posts_per_page 值到$c

STEP 6

使用array_combine 将两个阵列组合在一起。新创建的数组$c 将替换帖子数组的数组键

STEP 7

使用ksort 对使用创建的新数组进行排序array_combine 根据新钥匙。现在,这将对数组进行排序,以便按帖子日期对帖子进行排序,并且首先显示所需标记中的帖子,然后显示其余帖子

Step 8

使用array-values 将按键重置回起始位置0 并在数字上增加1

STEP 9

倒带循环以便我们可以重新运行循环

STEP 10

取消设置内部的原始数组$wp_query->posts 并将其替换为创建的新阵列。$wp_query->posts 现在将保存一个包含新订购的post order的数组

ALL TOGETHER NOW!!

下面的代码用于您的函数。php

function wpse161553_loop_sort($tag=\'\') {
    global $wp_query;
    $posts = $wp_query->posts; // Gets all post data from the main query

    $c = []; // Going to hold an array of new keys for later use
    if ( have_posts() ) {
        $count = 0; //Start the counter
        $ppp = get_option(\'posts_per_page\'); // Gets the backend posts per page option set. Will be used in conjustion with the counter

        while ( have_posts() ) {
            the_post();
                if( \'\' != $tag && has_tag($tag)) { // This will be the tag to test against, your desired tag
                    $c[] = $count++;
                }else{
                    $c[] = $ppp + $count++; // Adds posts per page value to each count to advance posts without desired tag past desired tag
                }
        }
    } 

    $posts_reordered  = array_combine( $c, $posts ); // Reset each post from main query\'s key with the new keys created by $c
        $posts_sorted = ksort($posts_reordered); // Sort the new array according to key
    $posts_reordered  = array_values($posts_reordered); // Reset keys to start at zero and increment by one

    rewind_posts(); // Reset the loop so we can run the loop again

    unset($wp_query->posts); //unset the original $wp_query->posts object array
    $wp_query->posts = $posts_reordered; // Set $wp_query->posts to the new reordered array

}

HOW IT WILL BE USED

在您的类别中。php或任何模板都可以将以下内容粘贴到循环上方。你不需要再做任何改变

wpse161553_loop_sort( \'NAME OF THE TAG TO APPEAR FIRST\' );
在哪里NAME OF THE TAG TO APPEAR FIRST 是所需标签的名称,贴子将首先显示

SO网友:Nicolai Grossherr

只是一个想法的简要草案,所以请注意,我还没有完全考虑并测试过这一点。我确信您可以通过这种方式执行排序操作。好吧,我想的是,为什么不the_posts 和使用usort 进行排序。其余的一切,尤其是条件,只是为了确保这不是在每个查询上都执行的,而是取决于实际的用例,因此必须相应地进行调整。

add_action(
    \'the_posts\',
    \'wpse161553_posts_with_tags_on_top_of_category\',
    10,
    2
);
function wpse161553_posts_with_tags_on_top_of_category(
    $posts,
    $wp_query
) {
    // we want this for one specific category
    $the_category = \'abc\';
    // we want the post with this tag on top 
    $the_tag      = \'xyz\';

    if (
        $wp_query->is_main_query()
        && is_category( $the_category )
    ) {
        // getting an array of post ids from category with tag
        $posts_with_tag = new WP_Query(
            array(
                \'category_name\' => $the_category,
                \'tag\'           => $the_tag,
                \'fields\'        => \'ids\'
            )
        );  
        // performing usort on referenced posts object
        usort(
            $posts,
            function (
                $post
            ) use (
                $posts_with_tag
            ) {
                // puts posts from the $posts_with_tag->posts array to the top
                if(
                    in_array (
                        $post->ID,
                        (array) $posts_with_tag->posts 
                     )
                ) {
                    return -1;
                } else {
                    return 1;
                }
            }
        );
    }

    return $posts;
} 

结束