WP_QUERY:为什么粘帖不是循环中的第一项?

时间:2016-03-02 作者:ronnyrr

我有个习惯WP_Query 基于循环的meta\\u值变量:

$meta_cat = get_sub_field(\'category\');
$posts = new WP_Query( array(
    \'cat\' => $meta_cat,
    \'posts_per_page\' => get_sub_field(\'recent_ppp\'),
) );
但不知何故,当我将帖子设置为粘性时,它不会显示为while循环中的第一项。

我知道ignore_sticky_posts 默认设置为false,所以我不想修改它。还尝试在de中查找order_by documentation 如果某个值与sticky post相关,但它不是。

虽然order_by => \'post__in\' 可能很接近:

保留数组中post\\uu中给定的post ID顺序

但当我设定post__in => get_options(\'sticky_posts\') only 粘帖正在显示。

如果不构建两个自定义循环(一个处理粘性帖子,另一个处理其他帖子),这是否可能实现?这将非常糟糕,因为并非所有类别都包含粘性帖子。

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

如果您查看包含粘滞的源代码,我们会发现以下情况WP_Query 继续包括粘性贴子

if (    $this->is_home 
     && $page <= 1 
     && is_array($sticky_posts) 
     && !empty($sticky_posts)  
     && !$q[\'ignore_sticky_posts\'] 
) {
大玩家是is_home 条件内部条件句WP_Query 是根据传递给它的参数设置的,而不是根据发生查询的页面设置的。因为你通过了cat 作为论据,is_home 将设置为false,并且is_category 将设置为true。因为is_home 设置为false时,上述条件将失败,并且不包括胶粘物。

可能的解决方法-未经测试,我们可以手动设置is_home 至true viapre_get_posts. 我们要做的就是通过\'wpse_is_home\' => true, 根据您的习惯WP_Query 例子

然后我们运行pre_get_posts 行动如下

add_action( \'pre_get_posts\', function ( $q )
{
    if ( true === $q->get( \'wpse_is_home\' ) ) 
        $q->is_home = true;
});
编辑我们可能只想显示与所查询类别相关的粘滞物。在这种情况下,我们应该删除不属于特定查询类别的胶粘物

我们可以尝试以下方法pre_get_posts 行动

add_action( \'pre_get_posts\', function ( $q )
{
    remove_action( current_action(), __FUNCTION__ );

    if ( true !== $q->get( \'wpse_is_home\' ) )
        return;

    // Make sure get_sub_field exists, if not, bail
    if ( !function_exists( \'get_sub_field\' ) )
        return;

    // Lets query everything to keep code clean
    $meta_cat = get_sub_field( \'category\' ); // Copied from your code
    $meta_cat = filter_var( $meta_cat, FILTER_VALIDATE_INT );
    // Make sure we have a value, if not, bail
    if ( !$meta_cat )
        return;

    $q->set( \'cat\', $meta_cat );

    // Set pagination if recent_ppp exists
    $ppp = get_sub_field( \'recent_ppp\');
    $ppp = filter_var( $ppp, FILTER_VALIDATE_INT );
    if ( $ppp )
        $q->set( \'posts_per_page\', $ppp );      

    // Set is_home to true 
    $q->is_home = true;

    // Get all stickies
    $stickies = get_option( \'sticky_posts\' );
    // Make sure we have stickies, if not, bail
    if ( !$stickies )
        return;

    // Query the stickies according to category
    $args = [
        \'post__in\'            => $stickies,
        \'posts_per_page\'      => -1,
        \'ignore_sticky_posts\' => 1, // Ignore stickies
        \'cat\'                 => $meta_cat,
        \'orderby\'             => \'post__in\',
        \'order\'               => \'ASC\',
        \'fields\'              => \'ids\' // Get only post ID\'s
    ];
    $valid_sticky_ids = get_posts( $args );

    // Make sure we have valid ids
    if ( !$valid_sticky_ids ) {
        $q->set( \'post__not_in\', $stickies );
        return;
    }

    // Remove these ids from the sticky posts array
    $invalid_ids = array_diff( $stickies, $valid_sticky_ids );

    // Check if we still have ids left in $invalid_ids
    if ( !$invalid_ids )
        return;

    // Lets remove these invalid ids from our query
    $q->set( \'post__not_in\', $invalid_ids );
});
在运行自定义查询之前,我们需要确保get_sub_field 存在,最重要的是get_sub_field( \'category\' ) 已设置且有效。这将避免灾难性的失败,这将导致所有帖子被退回。

你的WP_Query 看起来像这样,因为我们只需要通过\'wpse_is_home\' => true:

if (    function_exists( \'get_sub_field\' )
     && filter_var( get_sub_field( \'category\' ), FILTER_VALIDATE_INT )
) {
    $args = [
        \'wpse_is_home\' => true
    ];
    $posts_array = new WP_Query( $args ); // DO NOT USE $posts

    // Run your loop as normal
}

LAST EDIT

代码已测试并按预期工作

相关推荐

GET_POSTS查询大约需要40秒来执行

我在get\\u帖子中有一个元查询,它需要花很长时间才能完成。它工作得很好,但只是时间太长了。我有一个名为event. 在每个event 发布后,有自定义元数据:post\\U sort\\U日期(事件日期YmdHis 格式,用于排序)我需要做的是获取下一个事件,该事件相对于$year 和$month 变量。所以如果$year = 2021 和$month = 10 (2021 10月)然后应该在2021 11月或之后找到第一个事件。我下面的查询很好,但很慢。执行大约需要40秒,我不知道为什么。$next