web-dev-qa-db-ja.com

Pre_get_posts関数を使ってメタキーで投稿を除けますか?

私は多くの人がpre_get_postsの代わりにquery_postsフックを使うのを好むように見えます。以下のコードは機能し、メタキー "featured"を持つすべての投稿を表示します

function show_featured_posts ( $query ) {
    if ( $query->is_main_query() ) {
       $query->set( 'meta_key', 'featured' );
       $query->set( 'meta_value', 'yes' );
    }
}

add_action( 'pre_get_posts', 'show_featured_posts' );

しかし、私は 'featured' meta_keyを持つ投稿を 除外 からメインクエリから除外したいです。これの簡単な方法はありますか?

24
Carlisle

私は多くの人がquery_postsの代わりにpre_get_postsフックを使うのを好むのを見ます

わーい!

そのため、pre_get_postsWP_Queryオブジェクト をフィルタリングします。これは、query_posts()を介して実行できるすべてを意味し、$query->set()および$query->get()を介して実行できます。特にmeta_query属性を利用することができます( Codex を参照)。

$meta_query = array(
                 array(
                    'key'=>'featured',
                    'value'=>'yes',
                    'compare'=>'!=',
                 ),
);
$query->set('meta_query',$meta_query);

しかし..これは元の 'meta query'(もしあれば)を置き換えます。ですから、元のメタクエリを完全に置き換えたくなければ、私はお勧めします:

//Get original meta query
$meta_query = $query->get('meta_query');

//Add our meta query to the original meta queries
$meta_query[] = array(
                    'key'=>'featured',
                    'value'=>'yes',
                    'compare'=>'!=',
                );
$query->set('meta_query',$meta_query);

このようにして、既存のメタクエリと共にメタクエリを追加します。

$meta_queryrelationプロパティをANDまたはORに設定したい場合、またはしたくない場合があります(すべて、または少なくとも1つのメタクエリを満たす投稿を返すため)。

*注:このタイプのクエリは、 'featured'メタキーを持つ投稿を返しますが、その値はyesではありません。メタキーは存在しません 3.5でこれを行うことができるでしょう

33
Stephen Harris

一部の人がそれを利用する可能性がある場合に備えて、おすすめの投稿のための一時的な解決策を投稿したいと思います。ここではpre_get_postsフックを使いませんが、query_postsも使いません。問題は、私はメインのクエリで遊ぶ必要があり、SQLクエリの一部を実行する必要があるということです。どんな専門家でもコードをチェックして、それが問題ないかどうか、またパフォーマンスの問題を引き起こさないかどうかを私に知らせてもらえたら幸いです。誰かがより良いアプローチを取り、それを私たちと共有してくれれば、それは素晴らしいことです。

注目の投稿の作成クエリ

<?php 

$featured_query = new WP_query( array(
    'meta_key'       =>'featured', 
    'meta_value'     =>'yes', 
    'posts_per_page' => 5, 
    'no_found_rows'  => true
    )
);

while ($featured_query->have_posts()) : 

    $featured_query->the_post(); 
    //Stuff...

endwhile; 
wp_reset_postdata(); 

?>

メインクエリを作成し、おすすめのmeta_keyを持つ投稿を除外し、最近の投稿を5件に制限し、その他すべてを表示します。

<?php 

$excludeposts = $wpdb->get_col( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'featured' AND meta_value != '' ORDER BY post_id DESC LIMIT 0, 5" );

$main_query = new WP_Query( array(
    'post__not_in' => $excludeposts, 
    'paged' => $paged 
    ) 
);  

while ($main_query->have_posts()) : 

    $main_query->the_post();
    //Stuff...

endwhile;

?>
2
Carlisle

@Carlisleに返信して、注目のマークが付いた最新の5件の投稿を除外したい場合は、以下を実行することができます。 posts_per_pageを除外したい数に変更し、meta_queryを注目のカテゴリを指定する方法に変更します。

function cmp_exclude_featured_posts($query) {
    $exclude = array();  //Create empty array for post ids to exclude
    if ( $query->is_main_query() ) {
            $featured = get_posts(array(
                'post_type' => 'post',
                'meta_query' => array(
                    array(
                        'key' => 'featured',
                        'value' => '1',
                        'compare' => '==',
                    ),
                ),
                'posts_per_page' => 2
            ));

            foreach($featured as $hide) {
                $exclude[] = $hide->ID;
            }   

            $query->set('post__not_in', $exclude);
        }
}

add_filter( 'pre_get_posts', 'cmp_exclude_featured_posts' );
0
cpeckens