wake-up-neo.net

Schließen Sie die ersten 5 Posts bestimmter Kategorien in der Hauptschleife aus

Ich lese diesen Artikel darüber, wie man einen Versatz für eine bestimmte Kategorie in der Schleife festlegt. Ich habe mich gefragt, ob dies für mehr als nur eine Kategorie möglich ist.

Mein Problem mit dem in dem oben verlinkten Artikel vorgeschlagenen Code ist, dass ich ein einzelnes Widget verwende, um fünf Beiträge aus einer Kategorie anzuzeigen, die ich in den Widget-Optionen nach ID festlegen kann. Ich kann mich nicht darum kümmern, wie ich den post_ID der Posts sammle, die bereits durchgeschleift sind.

Situation:

Ich verwende benutzerdefinierte Widgets auf meiner Blog-Seite, um die 5 neuesten Beiträge in zwei angegebenen Kategorien anzuzeigen - nennen wir sie KategorieA und KategorieB.

Antwort auf die Frage von @Pieter Goosen in den Kommentaren: Ja, ich kann die Kategorie angeben, indem ich manuell eine ID in den Widget-Einstellungen eingebe und sie in der Datenbank speichere.

Unter diesen Widgets durchläuft die Blog-Seite alle meine Beiträge und zeigt sie an.

Wirkung:

Die Hauptschleife auf der Blog-Seite (die unter den Widgets) zeigt die Posts von Kategorie A und Kategorie B erneut an. Sie erscheinen doppelt, weil die obigen Widgets bereits die Kategorien A und B durchlaufen haben.

Frage:

Ist es möglich, die ersten fünf Beiträge von Kategorie A und Kategorie B in der Hauptschleife auszuschließen? Könnte es mit pre_get_posts gemacht werden? Verwenden Sie get_query_var? Wie?

EDIT

Meine eigenen Ansätze

ERSTER VERSUCH

Ich habe meine Widget-Codes folgendermaßen geändert:

global $do_not_duplicate;
while($featured_posts->have_posts()): $featured_posts->the_post(); 
    $do_not_duplicate[] = get_the_ID();

Da meine Widgets in meiner functions.php-Datei registriert werden, habe ich diese Zeilen hinzugefügt:

global $do_not_duplicate;
$do_not_duplicate = array();
include('widgets/widgets.php');

Schließlich habe ich beim index.php diese Zeile zur Hauptschleife hinzugefügt:

if(have_posts()) :
    global $do_not_duplicate;
    while(have_posts()): the_post();
        if( in_array( $post->ID, $do_not_duplicate ) ) continue;
        get_template_part('content');
    endwhile;
endif;

Bitte beachten Sie: Dies funktioniert im Grunde genommen, entfernt aber nicht die Posts aus der Hauptabfrage, sondern überspringt sie. Dies bedeutet, dass die Standardeinstellung posts_per_page nicht erfüllt wird und dies nicht mit Jetpack Infinite Scroll funktioniert. Auch die Verwendung von Globals ist nicht der richtige Weg.

ZWEITER VERSUCH

Ich habe den @ Birgire-Vorschlag angepasst und ein wenig modifiziert. Ich dachte darüber nach, den vorgeschlagenen pre_get_posts-Filter in Kombination mit einer foreach-Schleife für die Kategorien zu verwenden, die von den Widgets verwendet werden, um die IDs der von ihnen abgefragten Posts zu sammeln. Hier ist mein Ausschnitt:

add_action('pre_get_posts', 'modified_mainloop', 10);
function modified_mainloop($query) {
    if(!is_admin() && $query->is_home() && $query->is_main_query()) {
        $cats_to_exclude = get_categories('include=3,4,9');
        foreach($cats_to_exclude as $category) {
            if($category->term_id == '9') {
                $num_posts_to_exclude = 3;
            } else {
                $num_posts_to_exclude = 5;
            }
            $posts_to_exclude = get_posts(array(
                'posts_per_page' => $num_posts_to_exclude,
                'category__in'   => array($category->term_id),
                'fields'         => 'ids'
            ));

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

    }
}

Bitte beachten Sie: Idee ist in Ordnung, aber Code funktioniert nicht.

2
okiedokey

Hier ist ein Konzept, das Sie ausprobieren können, um 5 Posts pro Kategorie von Kategorie 3 und 5 auszuschließen, wobei Posts ausgeschlossen werden, die zu Kategorie 9 undeiner der zuvor genannten Kategorien gehören.

Hier ist die Funktion: (CAVEAT:Erfordert PHP 5.4+, da ich die neue Syntax für kurze Arrays verwendet habe. Ändern Sie sie nach Bedarf)

/**
 * function get_sticky_category_posts()
 *
 * Get an array of post ids according to arguments given.
 *
 * @author Pieter Goosen
 * @see https://wordpress.stackexchange.com/q/187477/31545
 *
 * @param array $args
 */
function get_sticky_category_posts( $args = [] )
{
    /*
     * If the array is empty or not valid, return null
     */
    if ( empty( $args ) || !is_array( $args ) )
        return null;

    $ids = '';

    foreach ( $args as $k=>$v ) {

        /*
         * Check that $v['taxonomy'], $v['included_terms'] and $v['posts_per_page'] are all set. If not, return null
         */ 
        if (    !isset( $v['taxonomy'] ) 
             || !isset( $v['included_terms'] )
             || !isset( $v['posts_per_page'] )
        )
        return null;

        /*
         * Sanitize and validate user input
         */
        $included_terms = filter_var( $v['included_terms'], FILTER_VALIDATE_INT, ['flags'  => FILTER_FORCE_ARRAY] );
        $taxonomy       = filter_var( $v['taxonomy'], FILTER_SANITIZE_STRING );

        /*
         * Create tax_query according to whether $v['excluded_terms'] is set
         */
        if ( !isset( $v['excluded_terms'] ) ) {
            $tax_query = [
                [
                    'taxonomy'         => $taxonomy,
                    'terms'            => $included_terms,
                    'include_children' => false,
                ],
            ];
        } else {
            $tax_query = [
                [
                    'taxonomy'         => $taxonomy,
                    'terms'            => $included_terms,
                    'include_children' => false,
                ],
                [
                    'taxonomy'         => $taxonomy,
                    'terms'            => filter_var( $v['excluded_terms'], FILTER_VALIDATE_INT, ['flags'  => FILTER_FORCE_ARRAY] ),
                    'include_children' => false,
                    'operator'         => 'NOT IN'
                ],
            ];
        } // endif ( !$v['excluded_term'] ) statement

        /*
         * Use get_posts to get an array of post ids to exclude
         */
        $posts_to_exclude = get_posts(
            [
                'posts_per_page' => filter_var( $v['posts_per_page'], FILTER_VALIDATE_INT ),
                'fields'         => 'ids',
                'tax_query'      => $tax_query
            ]
        );
        if ( $posts_to_exclude ) {

            /*
             * Concatenate all ids into a string using implode
             */
            $ids .= implode( ' ', $posts_to_exclude );
            $ids .= ' ';
        } //endif ( $posts_to_exclude )

    } //end foreach

    /*
     * If we don't have any ids, thus empty string, return null
     */
    if ( !$ids )
        return null;

    /*
     * Create a single flat array of post ids. Use rtrim to remove trailing white space
     */
    return explode( ' ', rtrim( $ids ) );
}

So funktioniert es:

  • Sie müssen den Argumenten der Funktion ein mehrdimensionales Array im folgenden Format übergeben

    $args = [
        0 => ['posts_per_page' => 5, 'taxonomy' => 'category', 'included_terms' => 3, 'excluded_terms' => 9],
        1 => ['posts_per_page' => 5, 'taxonomy' => 'category', 'included_terms' => 4, 'excluded_terms' => 9],
    ];
    $a = get_sticky_category_posts( $args );
    
  • Es gibt vier zulässige Parameter, von denen Sie müssenden posts_per_page, taxonomy und included_terms setzen (muss eine Ganzzahl oder ein Array von Term-IDs sein), andernfalls gibt die Funktion null zurück. Der andere zulässige Parameter (der nicht erforderlich ist und weggelassen werden kann) ist excluded_terms, der ebenfalls eine Ganzzahl oder ein Array von Term-IDs ist und die Begriffe darstellt, in denen sich ein Beitrag nicht befinden sollte folgende)

    • 5 Beitrags-IDs aus dem Taxonomiebegriff 3 aus dem Taxonomiebegriff category, aber Beiträge mit den Begriffen 3 und 9 sollten nicht zurückgegeben werden

    • 5 Beitrags-IDs aus dem Taxonomiebegriff 4 aus dem Taxonomiebegriff category, aber Beiträge mit den Begriffen 4 und 9 sollten nicht zurückgegeben werden

    • Das von der Funktion zurückgegebene Array (var_dump( $a )) sieht ungefähr so ​​aus

      array(10) {
        [0]=>
        string(3) "159"
        [1]=>
        string(3) "149"
        [2]=>
        string(3) "129"
        [3]=>
        string(3) "126"
        [4]=>
        string(3) "119"
        [5]=>
        string(2) "76"
        [6]=>
        string(3) "528"
        [7]=>
        string(3) "394"
        [8]=>
        string(3) "147"
        [9]=>
        string(2) "97"
      }
      

Dieses Array kann jetzt an pre_get_posts an den Parameter post__not_in übergeben werden, um die Posts von der Funktion auszuschließen. Sie können dieses Array von IDs auch an einer anderen Stelle verwenden und sie möglicherweise zu einer benutzerdefinierten Abfrage oder zu anderen Zwecken zurückgeben, z. B. zu Haftnotizen auf anderen Seiten, mit Ausnahme der in this answer :-) verwendeten Homepage.

Hier ist ein Anwendungsfall mit pre_get_posts. Dadurch werden die erforderlichen Beiträge aus der Hauptabfrage entfernt. (Erfordert PHP 5.4+ aufgrund der Syntax in der Funktion und der Verwendung von Closures (Closures sind verfügbar PHP 5.3+)

add_action( 'pre_get_posts', function ( $q )
{
    if (    !is_admin() // Not necessary for home page, included it to be used on any other template like category pages
         && $q->is_main_query() // Make sure this is the main query
         && $q->is_home() // Targets the home page only
    ) {
        if ( function_exists( 'get_sticky_category_posts' ) ) {

            $args = [
                0 => ['posts_per_page' => 5, 'taxonomy' => 'category', 'included_terms' => 3, 'excluded_terms' => 9],
                1 => ['posts_per_page' => 5, 'taxonomy' => 'category', 'included_terms' => 4, 'excluded_terms' => 9],
            ];
            $sticky_cat_posts = get_sticky_category_posts( $args );

            if ( !empty( $sticky_cat_posts ) ) {
                $q->set( 'post__not_in', $sticky_cat_posts );
            }   
        }
    }
}); 
3
Pieter Goosen

Sie könnten diese Art von pre_get_posts Hook-Ansatz ausprobieren (ungetestet):

add_action( 'pre_get_posts', function( $q )
{
    $exclude_cats = [ 12, 34 ]; // <-- Edit these category ids!

    if(    ! is_admin() 
        && $q->is_main_query()
        && ! is_singular()
        && ! is_category( $exclude_cats ) 
    )
    {
        $exclude_post_ids = get_posts( 
            [
                'fields'         => 'ids',
                'posts_per_page' => 5,
                'category__in'   => $exclude_cats,
            ]
        );
        $q->set( 'post__not_in', (array) $exclude_post_ids ); 
    }
} );

wo müssen Sie dies möglicherweise weiter an Ihre Bedürfnisse anpassen.

Möglicherweise möchten Sie stattdessen auch Category-Slugs verwenden, müssen dann aber einen richtigen tax_query einrichten, da category__in nur ein Array von Category-IDs unterstützt.

3
birgire