web-dev-qa-db-ja.com

最初にタグで、次にタグ関連で十分でない場合はカテゴリで関連する投稿のX件数にクエリを課税する方法

質問

最初にタグ関連の投稿を出力し、次にタグ関連の投稿が4つ未満の場合は、4つのスポットの残りをカテゴリ関連の投稿で埋めますか。

シナリオ

投稿にタグが非常に少ない、またはラベルが付いているタグに投稿が非常に少ない場合があります。 「タグで関連記事」を出力するとき、その領域は1つか2つの記事で非常にまばらか、または完全に空です。

これを解決するには、posts_per_page => Xを満たすのに十分なタグ関連の投稿がない場合、関連するカテゴリからの投稿を表示するのが良いでしょう。

だから、このようなもの:


シナリオA - タグ関連の投稿が4つ以上ある場合、次のようになります。

Related Posts:

Show the below posts:

1. tag-related post #1
2. tag-related post #2
3. tag-related post #3
4. tag-related post #4

Do Not show the below posts:

5. tag-related post #5
6. tag-related post #6
7. tag-related post #7
...

シナリオB - タグ関連の投稿が2つしかない場合、次のようになります。

Related Posts:

Show the below posts:

1. tag-related post #1
2. tag-related post #2  
3. category-related post #1
4. category-related post #2

Do Not show the below posts:

5. category-related post #3
6. category-related post #4
7. category-related post #5
...

私が試したこと

私が使用している税クエリ

// start of the tax_query arguments
$args = array( 'posts_per_page'=>4, 'post__not_in' => array($post->ID), 'tax_query' => array( 'relation' => 'OR' ) );

// get current post tags
$tags = wp_get_object_terms( $post->ID, 'post_tag', array( 'fields' => 'ids' ) );

if ( !empty( $tags ) ) {
    $args['tax_query'][] = array(
        'taxonomy' => 'post_tag',
        'field'    => 'id',
        'terms'    => $tags
    );
}

// get current post categories
$categories = wp_get_object_terms( $post->ID, 'category', array( 'fields' => 'ids' ) );

if ( !empty( $categories ) ) {
    $args['tax_query'][] = array(
        'taxonomy' => 'category',
        'field'    => 'id',
        'terms'    => $categories
    );
}

// the query
$related_query = new WP_Query( $args );

私が理解しているように、その税務照会は「同じカテゴリーに属する投稿を取得し、次に同じタグに含まれる投稿を取得し、そして4が表示されるまで投稿を出力する」と言っています。

それでも、画面上の4つの投稿ルールを満たし、最も重要なタグ関連の投稿を除外して、カテゴリ投稿を最初に出力し続けます(そのうち多くがあります)。私はANDの代わりにORを使ってコードを動かしてみました。

私はまたこれらの記事を見た: WordPress - タグで分類された投稿のリストを作成し、次にカテゴリ そして - Wordpressはタグと分類で投稿を検索する タグANDカテゴリによる。最初にタグで関連付けられた投稿が必要で、4以上の場合はそれらの上位4件を出力するだけです。4未満の場合は、4件の投稿基準を満たすために最大でカテゴリ関連の投稿を出力します。

明らかに質問や問題を誤解しているので、どんな助けでも評価されるでしょう。

溶液

Peterの解決策 完璧に動作します - Peterに感謝します!

私はさらに私自身の目的のためにそれを少し構築しました、そしてあなたの非常にコメントされたコードを使用して、私はこの質問から「最近の投稿」を除外することもできました - woohoo!

3
Andre Bulatov

1回のクエリでこれを実行することはできません。現時点でWP_Queryが実行できることに対して、これは少し高度すぎます。私たちはあなたが望むものを達成するためにここで少なくとも2つの( 私は3 )を使うつもりです。

最初の質問

最初のクエリはpost_tagに従って投稿を検索します。これは現在の投稿も除外します。投稿IDのみを取得します

2回目の質問

この問い合わせはcategory分類法から来る "fill-up"投稿を処理します。このクエリが成功するには、以下が必要になります。

  • 重複する投稿を避けるために、現在の投稿と最初のクエリからの投稿を除外します。

  • 最初のクエリの投稿数を取得し、4からそれを減算してから、その差分を使用して、このクエリで取得する必要がある投稿の数を設定します。

私達はまたちょうどポストIDをここに得るでしょう

3回目の質問

クエリオブジェクトからの整合性を保つために、前のクエリからのすべてのIDを組み合わせて、最終的な投稿オブジェクトをクエリします。これは高価だと思うかもしれませんが、そうではありません。最初の2つのクエリはget_posts()を使用し、投稿IDのみを取得するので、それらは本当に超高速です。 IDのみを照会することで、キャッシュを更新しないため、これらの照会はさらに高速になります。

溶液

私はテンプレートをきれいに保つためにコードのような大きな部分のための関数を作成することを好みます。次の点に注意してください 未テストであり PHP 5.4が必要です

function get_max_related_posts( $taxonomy_1 = 'post_tag', $taxonomy_2 = 'category', $total_posts = 4 )
{
    // First, make sure we are on a single page, if not, bail
    if ( !is_single() )
        return false;

    // Sanitize and vaidate our incoming data
    if ( 'post_tag' !== $taxonomy_1 ) {
        $taxonomy_1 = filter_var( $taxonomy_1, FILTER_SANITIZE_STRING );
        if ( !taxonomy_exists( $taxonomy_1 ) )
            return false;
    }

    if ( 'category' !== $taxonomy_2 ) {
        $taxonomy_2 = filter_var( $taxonomy_2, FILTER_SANITIZE_STRING );
        if ( !taxonomy_exists( $taxonomy_2 ) )
            return false;
    }

    if ( 4 !== $total_posts ) {
        $total_posts = filter_var( $total_posts, FILTER_VALIDATE_INT );
            if ( !$total_posts )
                return false;
    }

    // Everything checks out and is sanitized, lets get the current post
    $current_post = sanitize_post( $GLOBALS['wp_the_query']->get_queried_object() );

    // Lets get the first taxonomy's terms belonging to the post
    $terms_1 = get_the_terms( $current_post, $taxonomy_1 );

    // Set a varaible to hold the post count from first query
    $count = 0;
    // Set a variable to hold the results from query 1
    $q_1   = [];

    // Make sure we have terms
    if ( $terms_1 ) {
        // Lets get the term ID's
        $term_1_ids = wp_list_pluck( $terms_1, 'term_id' );

        // Lets build the query to get related posts
        $args_1 = [
            'post_type'      => $current_post->post_type,
            'post__not_in'   => [$current_post->ID],
            'posts_per_page' => $total_posts,
            'fields'         => 'ids',
            'tax_query'      => [
                [
                    'taxonomy'         => $taxonomy_1,
                    'terms'            => $term_1_ids,
                    'include_children' => false
                ]
            ],
        ];
        $q_1 = get_posts( $args_1 );
        // Count the total amount of posts
        $q_1_count = count( $q_1 );

        // Update our counter
        $count = $q_1_count;
    }

    // We will now run the second query if $count is less than $total_posts
    if ( $count < $total_posts ) {
        $terms_2 = get_the_terms( $current_post, $taxonomy_2 );
        // Make sure we have terms
        if ( $terms_2 ) {
            // Lets get the term ID's
            $term_2_ids = wp_list_pluck( $terms_2, 'term_id' );

            // Calculate the amount of post to get
            $diff = $total_posts - $count;

            // Create an array of post ID's to exclude
            if ( $q_1 ) {
                $exclude = array_merge( [$current_post->ID], $q_1 );
            } else {
                $exclude = [$current_post->ID];
            }

            $args_2 = [
                'post_type'      => $current_post->post_type,
                'post__not_in'   => $exclude,
                'posts_per_page' => $diff,
                'fields'         => 'ids',
                'tax_query'      => [
                    [
                        'taxonomy'         => $taxonomy_2,
                        'terms'            => $term_2_ids,
                        'include_children' => false
                    ]
                ],
            ];
            $q_2 = get_posts( $args_2 );

            if ( $q_2 ) {
                // Merge the two results into one array of ID's
                $q_1 = array_merge( $q_1, $q_2 );
            }
        }
    }

    // Make sure we have an array of ID's
    if ( !$q_1 )
        return false;

    // Run our last query, and output the results
    $final_args = [
        'ignore_sticky_posts' => 1,
        'post_type'           => $current_post->post_type,
        'posts_per_page'      => count( $q_1 ),
        'post__in'            => $q_1,
        'order'               => 'ASC',
        'orderby'             => 'post__in',
        'suppress_filters'    => true,
        'no_found_rows'       => true
    ];
    $final_query = new WP_Query( $final_args );

    return $final_query;
}

あなたは今、あなたの単一のテンプレートで以下のように関数を使うことができます

$query = get_max_related_posts();
if ( $query ) {

    while ( $query->have_posts() ) {
        $query->the_post();

            echo get_the_title() . '</br>';

    }
    wp_reset_postdata();
}

いくつかの注意

  • デフォルトはすでに3つのパラメータに対してそれぞれpost_tagcategoryおよび4に設定されているので、それを呼び出すときには関数に値を渡す必要があります。

  • 分類法を取り替えたり、異なる分類法を設定したり、ページごとの投稿数を4以外に設定したりする必要がある場合は、単純に関数に正しい順序で渡します。

    $query = get_max_related_posts( 'tax_1', 'tax_2', 6 );
    
3
Pieter Goosen