it-swarm.com.de

Begrenzung der Anzahl benutzerdefinierter Posts, die auf der Taxonomieseite angezeigt werden

Ich verwende einen benutzerdefinierten Beitragstyp, der die zwei Taxonomien "Farbe" und "Stil" verwendet. Ich habe ein Skript ( aus diesem Thread ), das sie so gruppiert, dass sie auf einer Farbtaxonomieseite nach Stil wie folgt gruppiert sind:

Blau> Stil 1

  • Produkt 1
  • Produkt 2
  • Produkt 3
  • Produkt 4
  • Produkt 5

Blau> Stil 2

  • Produkt 1
  • Produkt 2
  • Produkt 3
  • Produkt 4
  • Produkt 5

Jetzt funktioniert alles super, aber es gibt JEDEN Beitrag zurück. Ich möchte es auf die ersten drei Beiträge für jeden Stil beschränken. Ich weiß, dass ich etwas wie das Folgende tun kann, aber es beschränkt die Beiträge für die gesamte Seite nicht pro Stil. Irgendeine Hilfe? :)

//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

Wie ich in den Kommentaren ausgeführt habe, wird dies einige Arbeit erfordern. Kurz gesagt, benötigen Sie Folgendes:

  • Holen Sie sich alle Begriffe aus der Taxonomie style. Hier würden wir nur den Begriff IDs wollen

  • Rufen Sie den aktuellen tax_query aus der Taxonomie colour ab. Verwenden Sie jeden Begriff aus der Taxonomie style und erstellen Sie einen neuen tax_query, um Beiträge aus dem Begriff der aktuellen Seite und dem Begriff zu erhalten, der aus der Taxonomie style in einer Schleife weitergeleitet wird

  • Führen Sie eine benutzerdefinierte Abfrage für jeden Begriff aus der Taxonomie style aus, um eine Reihe von Post-IDs für jeden Begriff abzurufen. Hier möchten Sie alle Ihre benutzerdefinierten Parameter hinzufügen. Wir verwenden die Bestellung aus diesen benutzerdefinierten Abfragen als Nachbestellung

  • Übergeben Sie das Array der Post-IDs an die Hauptabfrage. Hier möchten Sie keine benutzerdefinierte Sortierung usw. hinzufügen. Für die Sortierung verwenden wir die Reihenfolge der Post-IDs im Post-ID-Array

EINIGE HINWEISE VOR DEM CODE:

  • Für den Code ist PHP 5.4+ erforderlich, da die Syntax für kurze Arrays ([]) verwendet wird. Sie sollten auch keine ältere Version als PHP5.4 verwenden. Ändern Sie in diesem Fall einfach die kurze Array-Syntax in die alte Array-Syntax (array()). Zum Beispiel sollte get_terms( $taxonomy, ['fields' => 'ids'] ) zu get_terms( $taxonomy, array( 'fields' => 'ids' ) ) werden

  • Ich habe ein vorübergehendes System eingebaut, um die zusätzliche Belastung zu reduzieren, die durch all die zusätzliche Arbeit entsteht, die wir tun müssen. Dieser Übergang läuft in einer Woche ab. Sie können ihn länger oder kürzer einstellen. Der Übergang wird automatisch gelöscht, wenn ein neuer Beitrag veröffentlicht, gelöscht, wiederhergestellt oder aktualisiert wird

  • Ich habe den Code sehr gut kommentiert, damit Sie dem folgen und einen Sinn daraus ziehen können, was ich im Laufe der Zeit gemacht habe

  • Sie können nach Bedarf erweitern und ändern. Achte darauf, meine Kommentare zu lesen

  • Mit diesem neuen Code können Sie meine Idee der Sortierung aufgeben, wie in meiner verknüpften Antwort auf SO beschrieben. Der in dieser Antwort angegebene Code sollte sich um diese Sortierung kümmern. Alle Anpassungen, die Sie vornehmen möchten, sollten in den benutzerdefinierten Abfragen und get_terms -Aufrufen vorgenommen werden. Denken Sie daran, Ihre Transienten nach jeder Änderung zu löschen, oder kommentieren Sie die transienten Anrufe besser aus und kehren Sie zum Normalzustand zurück, sobald Sie mit all Ihren Änderungen zufrieden sind

DER CODE:

Wie immer verwenden wir pre_get_posts, um die Hauptabfrage nach Bedarf zu ändern

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
});

Damit wird alles erledigt, außer das Löschen der Transienten beim Veröffentlichen, Löschen usw

Der folgende Code kümmert sich darum. Jedes Mal, wenn ein Beitrag aktualisiert, veröffentlicht, verworfen oder nicht verworfen wird, wird der Haken "transition_post_status" ausgelöst, sodass wir diese Logik verwenden, um alle unsere Transienten zu löschen, die einen Teil des Namens "colourtax_" enthalten

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

Ok, ich glaube, ich habe einen Weg gefunden, dies zu tun. Obwohl ich sagen muss, dass ich es noch nicht ausprobiert habe und es wahrscheinlich nicht der beste Weg ist. Freut mich, andere Lösungen zu sehen.

Was ich getan habe, ist ein Meta-Feld in meinem benutzerdefinierten Post mit einem Optionsfeld, das die Optionen "Hervorgehoben" und "Nicht Hervorgehoben" enthält. Ich setze die drei benutzerdefinierten Posts für jede Gruppe, die ich anzeigen möchte, und filtere die Hauptabfrage mit dem passenden Metaschlüssel. Wie so:

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