忽略主查询中的元值POST

时间:2016-03-08 作者:nicogaldo

我使用此函数在循环的开头插入两个便利的帖子(带有元键和值)

add_filter( \'posts_results\', \'insert_post_wpse_96347\', 10, 2 );
function insert_post_wpse_96347( $posts, \\WP_Query $q ) {
    remove_filter( current_filter(), __FUNCTION__ );

    if ( $q->is_main_query() && $q->is_home() && 0 == get_query_var( \'paged\' ) ) {

        $args = [
            \'meta_key\'         => \'caja\', 
            \'meta_value\'       => [\'uno\',\'dos\'], 
            \'post__not_in\'     => get_option( "sticky_posts" ), 
            \'posts_per_page\'   => \'2\',
            \'suppress_filters\' => true
        ];

        $p2insert = new WP_Query($args);
        $insert_at = 0;
        if ( !empty( $p2insert->posts ) ) {
            array_splice( $posts, $insert_at, 0, $p2insert->posts );
        }
    }
  return $posts;
}
但这些帖子仍然会出现在循环中,它们必须隐藏起来才能不看两遍。

我该怎么做?

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

我们可以尝试以下替代方法:

从主查询中通过pre_get_posts 行动

通过返回第一页顶部的两篇文章the_posts 滤器

让我们看看可能的代码:

add_action( \'pre_get_posts\', function ( $q )
{
    remove_filter( current_filter(), __FUNCTION__ );

    if (    $q->is_home()       // Only target the home page     
         && $q->is_main_query() // Only target the main query
    ) {
        // Set our query args and run our query to get the required post ID\'s
        $args = [
            \'meta_key\'         => \'caja\', 
            \'meta_value\'       => [\'uno\',\'dos\'], 
            \'posts_per_page\'   => \'2\',
            \'fields\'           => \'ids\', // Get only post ID\'s
        ];      
        $ids = get_posts( $args );

        // Make sure we have ID\'s, if not, bail
        if ( !$ids )
            return;

        // We have id\'s, lets remove them from the main query
        $q->set( \'post__not_in\', $ids );

        // Lets add the two posts in front on page one
        if ( $q->is_paged() )
            return;

        add_filter( \'the_posts\', function ( $posts, $q ) use ( $args )
        {
            if ( !$q->is_main_query() )
                return $posts;

            // Lets run our query to get the posts to add
            $args[\'fields\'] = \'all\';
            $posts_to_add   = get_posts( $args );

            $stickies = get_option( \'sticky_posts\' );
            if ( $stickies ) {
                $sticky_count = count( $stickies );
                array_splice( $posts, $sticky_count, 0, $posts_to_add );

                return $posts;
            }

            // Add these two posts in front
            $posts = array_merge( $posts_to_add, $posts );

            return $posts;
        }, 10, 2 );
    }
}); 
这应该替换您在问题中发布的当前代码

SO网友:Adam

请尝试以下操作:

NOTE: make sure to add any extra conditional logic you need for your usecase, such as a check for is_home() and the value for get_query_var( \'paged\' ). I have intentionally left those out just for brevity.

function custom_pre_get_posts_meta_query( $query ) {

    if ( is_admin() || ! $query->is_main_query() )
        return;


    $meta_key = \'caja\'; //meta_key to query

    $query->set( 
        \'orderby\', 
        array(
            \'meta_value\' => \'DESC\',
            \'date\'       => \'DESC\'
        ) 
    );

    $query->set( 
        \'meta_query\', 
        array(
            array(
                \'key\'     => $meta_key,
                \'value\'   => \'IGNORE THIS VALUE\', //this just needs to be something random
                \'compare\' => \'NOT EXISTS\'
            )
        )
    );

    add_filter( \'posts_where\', \'custom_where_meta_query\' );

}   

add_action( \'pre_get_posts\', \'custom_pre_get_posts_meta_query\', 1 );


function custom_where_meta_query( $where = \'\' ){

    global $wpdb;

    $meta_key    = \'caja\'; //meta_key
    $meta_values = array(\'uno\', \'dos\'); //meta_values

    $sql = "\'" . implode( "\', \'", array_map( \'esc_sql\', $meta_values ) ) . "\'";

    $where .= $wpdb->prepare( 
        " OR (( {$wpdb->postmeta}.meta_key = %s AND {$wpdb->postmeta}.meta_value IN ( {$sql} ) ))", 
        $meta_key
    );

    remove_filter( \'posts_where\', \'custom_where_meta_query\' );

    return $where;

}
上的第一个回调函数pre_get_posts 将启动WP_Meta_Query 它构建了必要的SQL,然后在第二个回调函数中对其进行过滤。

结果首先由排序meta_value DESC 然后由date DESC. 这将为元键分组两个匹配的帖子caja 在顶部,其余职位将按日期排序。

这避免了您必须在数据库中重新查询所需的两个特定帖子,然后拼接结果集,最后清除重复的结果集。

相关推荐

WordPress Custom Post Loop

我正在尝试循环浏览自定义WordPress帖子,遇到了一个问题,比如我添加了自定义字段并想在中显示它<li> 使用循环。我成功地完成了操作,但数据/链接/类别正在重复,如果类别与以下内容相同,我希望只显示一次:如果我有2篇带有data1类别的帖子,那么链接将只显示data1once 但我有2个不同类别的帖子,然后它会分别显示每个帖子。Sample Code:<ul class="filter filter-top"> <li cla