pre_get_posts関数を使用してメタキーで投稿を除外できますか?


24

多くの人がのpre_get_posts代わりにフックを使うことを好むようですquery_posts。以下のコードは機能し、メタキーが「機能」しているすべての投稿を表示します

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を含む投稿はメインクエリから除外されます。これのための簡単な方法はありますか?

回答:


33

多くの人がquery_postsの代わりにpre_get_postsフックを使用することを好むようです

わーい!

だから、pre_get_postsフィルタWP_Queryオブジェクトを意味しを経由してあなたができるquery_posts()あなたが経由で行うことができます$query->set()し、を$query->get()。特に、meta_query属性を使用できます(コーデックスを参照)。

$meta_query = array(
                 array(
                    'key'=>'featured',
                    'value'=>'yes',
                    'compare'=>'!=',
                 ),
);
$query->set('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);

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

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

* 注:このタイプのクエリは、「特集」メタキーを持つ投稿を返しますが、その値はyesです。「注目の」メタキーが存在しない投稿は含まれません。3.5でこれを行うことができます


だから、投稿のmeta_keyが存在するかどうかをチェックする方法はありません/空であるかどうか?3.5待つ必要があります。その後。お返事をありがとうございます。
カーライル

私は単純にメタとボックスが作成されますYesと、Noデフォルトで選択されたオプションと「いいえ」を。投稿を紹介する場合は、を選択しますYes。ただし、最後の5件の投稿は引き続き掲載され、他の投稿はメインクエリに表示されます。私は戻って毎回選択を変更したくないので、最新の5投稿のみを除外する方法を見つけなければなりません。stackexchangeについても同様の質問がたくさんありますが、これらの特集記事を管理する簡単な方法があるはずです。(一般的なパフォーマンスに影響を与えず、多くのクエリを作成せず、混合SQLクエリを必要としない方法)
Carlisle

ところで、すべての投稿に追加のmeta_keyを作成するのが良いアイデアなのか、YesそれともNo値を作成するのが良いアイデアなのかわかりません。単にfeaturedキーが欠けている投稿を除外することは素晴らしいことです。
カーライル

この関数は、PHP 7にアップグレードした後、元のサイトがnullとして返されUncaught Error: [] operator not supported for stringsていたためエラーをスローして、サイトで故障しましたmeta_query。あなたは何も出て切り替えない存在する場合は空の配列にフォールバックすることにより、それを回避することができます$meta_query = $query->get('meta_query');のために$meta_query = ( is_array( $query->get('meta_query') ) ) ? $query->get('meta_query') : [];
ケビンニュージェント

2

一部の人々がそれを利用する可能性がある場合に備えて、特集記事の一時的な解決策を投稿したいと思います。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;

?>

0

@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' );
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.