web-dev-qa-db-ja.com

分類法ページに表示される顧客投稿の数を制限する

「色」と「スタイル」という2つの分類法を使用したカスタム投稿タイプを使用しています。カラー分類ページにいるとき、それらがスタイルによってこのように分類されるように、私はそれらを一緒にグループ化するスクリプト(このスレッドからの)を持っています:

ブルー>スタイル1

  • 商品1
  • 商品2
  • 商品3
  • 商品4
  • 商品5

ブルー>スタイル2

  • 商品1
  • 商品2
  • 商品3
  • 商品4
  • 商品5

今、これはすべてうまくいきますが、すべての投稿を返します。各スタイルの最初の3つの投稿に限定したいと思います。私は次のようなことができると知っていますが、それはスタイルごとではなくページ全体の投稿を制限します。何か手助け? :)

//limit to three per style
add_action('pre_get_posts', 'change_tax_num_of_posts' );

function change_tax_num_of_posts( $wp_query ) {

    if( is_tax('colour') && is_main_query() ) {

      $wp_query->set('posts_per_page', 3);

    }

}
2
caffeinehigh

コメントで述べたように、これにはいくらかの作業が必要です。要するに、次のものが必要です。

  • style分類からすべての用語を取得します。ここでは、idという用語のみが必要です。

  • colour分類から現在のtax_queryを取得します。 style分類法の各用語を使用し、新しいtax_queryを作成して、現在のページの用語とstyle分類法からループされている用語から投稿を取得します

  • style分類から各用語に対してカスタムクエリを実行し、各用語から投稿IDの配列を取得します。ここで、すべてのカスタムパラメータを追加します。このカスタムクエリの順序をポストオーダーとして使用します

  • 投稿IDの配列をメインクエリに渡します。ここでは、カスタム並べ替えなどを追加したくないでしょう。並べ替えには、投稿ID配列の投稿IDのシーケンスを使用します

コードの前の注意事項:

  • 短い配列構文([])を使用するため、コードにはPHP 5.4+が必要です。また、PHP5.4より古いバージョンを使用しないでください。ただし、そうする場合は、短い配列構文を古い配列構文(array())に変更するだけです。たとえば、get_terms( $taxonomy, ['fields' => 'ids'] )get_terms( $taxonomy, array( 'fields' => 'ids' ) )になります

  • 一時的なシステムを構築して、必要な余分な作業から生じる余分な負担を軽減しています。このトランジェントは1週間で期限切れになるように設定されていますが、これを長くしたり短くしたりすることができます。新しい投稿が公開、削除、削除されていない、または更新されると、一時的な投稿は自動的に削除されます

  • 私はコードを非常によくコメントしているので、あなたは私が一緒に行ったときに何をしていたのかを理解することができます

  • 必要に応じて拡張および変更できます。コメントを必ずチェックしてください

  • この新しいコードを使用すると、 SOに関するリンクされた回答 で説明されているように、並べ替えに関する私の完全なアイデアを破棄できます。この回答に記載されているコードは、このソートを処理する必要があります。必要な調整は、カスタムクエリとget_terms呼び出しで行う必要があります。変更するたびにトランジェントをフラッシュすることを忘れないでください。または、すべての変更に満足したら、トランジェントコールのコメントを解除して通常の状態に戻してください。

コード:

いつものように、必要に応じてpre_get_postsを使用してメインクエリを変更します

add_action( 'pre_get_posts', function ( $q )
{       
    if (    !is_admin() // Targets only front end queries
         && $q->is_main_query() // Targets only main query
         && $q->is_tax( 'colour' ) // Targets only taxonomy pages
    ) {

        /** 
         * To save on the extra work that we need to do to get our results,
         * lets save everything in a transient. We will save the string of post ids
         * in the transient. 
         *
         * We will only delete and recreate this transient when a new post is published,
         * deleted, undeleted or updated. This will save us a lot of extra hard work
         * on every page load
         *
         * @link https://codex.wordpress.org/Transients_API
         */
        $queried_object = get_queried_object(); // Get the current queried object to build a unique transient name
        /**
         * Use md5 to build a unique transient name to avoid any conflicts
         * The code below will create a unique transient name which will look like this
         * "colourtax_1ac37e97ee207e952dfc2b8f7eef110f"
         *
         * Note, this should NOT be longer that 45 characters else the transient will be regenerated
         * on each page load. Transients are expensive to create, so don't want to recreate this on every
         * page load due to a name being to long. As a quick guide the md5 part generate a 32 character string,
         * so the "colourtax_" part should be a maximum of 13 characters
         */
        $unique_transient_name = 'colourtax_' . md5( $queried_object->taxonomy . $queried_object->slug . $queried_object->term_id );
        if ( false === ( $post_ids_array = get_transient( $unique_transient_name ) ) ) {

            // Gets the current tax_query
            $tax_query = $q->tax_query->queries; 
            // Choose the taxonomy to sort by
            $taxonomy = 'style'; 
            // Set the variable to hold the sorted post ids according to terms
            $post_ids_array = [];

            /**
             * Get all the terms from the selected taxonomy to sort by. Just get term ids
             * Add additional arguments here as needed
             * 
             * @link https://codex.wordpress.org/Function_Reference/get_terms
             */
            $terms = get_terms( $taxonomy, ['fields' => 'ids'] ); 
            if (    $terms // Check if the array has valid terms, not empty
                 && !is_wp_error( $terms ) // Check that we do not have any error
            ) { 
                // Define a variable to hold all post ID
                $posts_ids = '';
                foreach ( $terms as $term ) {
                    /**
                     * NOTE: You would want to do everything here
                     *
                     * Build our query args, add all your relevant arguments here
                     * You should extend this to include your custom parameter values
                     * like meta_queries en sorting order.
                     * Do a var_dump( $wp_query ) and use the relevant arguments from
                     * there to make this dynamic
                     */
                    $args = [
                        'post_type' => 'any',
                        'posts_per_page' => 3, // Get only 3 posts per term
                        'fields' => 'ids', // Only get post ids to make query faster and more lean
                        // Build a tax_query to add additional terms from selected taxonomy to sort by  
                        'tax_query' => [ 
                            $tax_query, // Our default tax_query from the taxonomy page
                            [
                                'taxonomy' => $taxonomy,
                                'terms' => $term,
                                'include_children' => false,
                            ],
                        ],
                    ];
                    // Return an array of post ids only
                    $posts_array = get_posts( $args );
                    // First check if we have posts to avoid bugs in our code
                    if ( $posts_array ) {
                        // Break the ids array up into a string for later processing
                        foreach ( $posts_array as $v )
                            $posts_ids .= ' ' . $v;
                        unset( $v );    
                    } //endif $posts_array

                } //endforeach $terms
                unset( $term );

                // ADDITIONAL, CAN DELETE THE FOLLOWING SECTION IF YOU WANT TO. READ COMMENTS BELOW

                /**
                 * You can remove the following section. The idea here is as follow:
                 * Any post without a term in the style taxonomy will not be displayed on
                 * a colour taxonomy term page. To avoid this, we will need to get all posts
                 * that does not have a post in style taxonomy. This posts will be displayed last
                 * on the page
                 *
                 * If you are very sure that all posts are tagged in a colour AND style taxonomy
                 * term, then you can remove this section, this is really just a fall back
                 */
                $args_additional = [
                    'post_type' => 'any',
                    'posts_per_page' => 3, // Get only 3 posts without style taxonomy term, adjust as needed
                    'fields' => 'ids', // Only get post ids to make query faster and more lean
                    // Build a tax_query to get posts that is not tagged in style taxonomy  
                    'tax_query' => [ 
                        $tax_query, // Our default tax_query from the taxonomy page
                        [
                            'taxonomy' => $taxonomy,
                            'terms' => $terms,
                            'include_children' => false,
                            'operator' => 'NOT IN', // Posts should not have these terms from style taxonomy
                        ],
                    ],
                ];
                // Return an array of post ids only
                $posts_array_2 = get_posts( $args_additional );
                // First check if we have posts to avoid bugs in our code
                if ( $posts_array_2 ) {
                    // Break the ids array up into a string for later processing
                    foreach ( $posts_array_2 as $v )
                        $posts_ids .= ' ' . $v;
                    unset( $v );    
                } //endif $posts_array

                // STOP DELETING HERE!!

                // Create an array of post ids from the $posts_ids string
                $post_ids_array = explode( ' ', ltrim( $posts_ids ) );

            } //endif $terms

            /**
             * Set the transient if it does not exist. 
             * NOTE: We will choose a week for expiry date, set as needed
             *
             * @link https://codex.wordpress.org/Transients_API#Using_Time_Constants
             */     
            set_transient( $unique_transient_name, $post_ids_array, 7 * DAY_IN_SECONDS );   
        } // endif transient check

        /**
         * Check if we have an array of post ID's before changing anything on the tax page
         *
         * Here we will alter the main query. You do not want to add or remove anything
         * here. Any custom parameters like sorting should be done in the custom queries
         * above
         *
         * DO NOT CHANGE ANYTHING IN THE CODE BELOW EXCEPT posts_per_page
         */
        if ( !empty( $post_ids_array ) ) {
            $q->set( 'post__in', $post_ids_array ); // Posts to get as set in our array, max of 3 posts per term
            $q->set( 'orderby', 'post_in' ); // Sort our posts in the order it is passed in the post__in array
            $q->set( 'order', 'ASC' );
            $q->set( 'posts_per_page', -1 ); // You can change this, if I remember, you need all posts on one page
        }

    } //endif conditional checks for query
});

これにより、ポストパブリッシュ、削除などのトランジェントのフラッシュを除くすべてが処理されます。

次のコードがこれを処理します。投稿が更新、公開、ゴミ箱またはゴミ箱に入れられるたびに、transition_post_statusフックが起動するので、そのロジックを使用して、colourtax_名の一部を含むすべてのトランジェントを削除します

add_action( 'transition_post_status', function ()
{
    global $wpdb;
    $wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE ('_transient%_colourtax_%')" );
    $wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE ('_transient_timeout%_colourtax_%')" );
});
1
Pieter Goosen

わかりました、私はこれをする方法を見つけたと思います。私はまだそれをテストしていないと言わなければならないがそれはおそらく最善の方法ではありません。他の解決策を見てうれしいです。

私が行ったことは、オプションが「おすすめ」と「未掲載」のラジオボタンを使用してカスタム投稿にメタボックスを作成することです。表示したい各グループの3つのカスタム投稿を設定してから、一致するメタキーでメインクエリをフィルタリングします。そのようです:

function colour_tax_featured($query) {

if( is_tax('colour') && $query->is_main_query() ) {

    $query->set('meta_key', 'meta_box_featured_colour');
        $query->set('meta_value', 'featured_colour');
    return $query;
}

 }

    add_action('pre_get_posts', 'colour_tax_featured' );
0
caffeinehigh