WP_Query Pagination auf single-custom.php

16

Was ich machen möchte:

Richten Sie die WP_QueryPaginierung in einer einzelnen benutzerdefinierten post-type.php-Vorlagendatei ein

Was habe ich getan

1) Erstellt einen Beitragstyp namens "Autoren". Jeder Beitrag innerhalb dieses Beitragstyps ist ein einzelner Autor.

2) Standardmäßige Seiten zum Bearbeiten von Beiträgen enthalten ein Dropdown-Menü, in dem alle Beiträge (Autoren) des benutzerdefinierten Beitragstyps des Autors aufgelistet sind.

3) Es wurde eine Vorlage für die Datei "single-authors.php" erstellt, in der alle Posts mit den Autoren-Metadaten aus der Dropdown-Liste abgefragt werden. Das Ergebnis ist eine Liste der Posts, denen derselbe Autor zugewiesen ist (eine Art Archiv):

<?php

// set the "paged" parameter (use 'page' if the query is on a static front page)
global $paged;

/*We need this here to add and maintain Pagination if Template is assigned to Front Page*/
if ( get_query_var( 'paged' ) ) {
    $paged = get_query_var('paged');
} elseif ( get_query_var( 'page' ) ) {
    $paged = get_query_var( 'page' );
} else {
    $paged = 1;
}

$args = array(
    'posts_per_page'    =>  10,
    'meta_key'          => 'author_select',
    'meta_value'        => $author_id,
    'paged'             => $paged,
);

$temp = $wp_query;
$wp_query = NULL;

$wp_query = new WP_Query($args);

?>

<?php if( $wp_query->have_posts() ) : ?>    
    <?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>
    <?php // Successfully outputs the results of the above query, so I've omitted the code from this example. ?>

    <?php endwhile; ?>

<div class="single_navigation"> 
    <?php if( get_adjacent_post( false, '', true ) ) { ?>
        <span class="prev"><?php previous_post_link( '&lt; %link' ) ?></span>
    <?php } ?>

    <?php if( get_adjacent_post( false, '', false ) ) { ?>
        <span class="next"><?php next_post_link( '%link &gt;' ) ?></span>
    <?php } ?>
    </div><!--/single navigation-->
<?php endif; ?>

<?php
    $wp_query = null;
    $wp_query = $temp;
    wp_reset_query();
?>

Woran ich festhalte

Die Paginierungslinks werden nicht angezeigt. Ich habe einige Nachforschungen angestellt und festgestellt, dass sie die $wp_queryVariable verwenden. Als ich jedoch meine Abfragevariable in änderte $wp_query, erschienen die Links, aber wenn geklickt wurde, geschah nichts.

Irgendeine Idee, wo ich falsch liege?

Bearbeiten:

Um einige Ihrer Fragen zu beantworten, gibt meine Abfrage die von mir abgefragten Posts erfolgreich aus. $ Author_id hat bereits einen Wert, den ich nicht in dieses Code-Snippet aufgenommen habe. Ebenso habe ich die eigentliche Inhaltsausgabe in der while-Schleife ausgelassen, da dieser Teil nicht das Problem ist. Das Problem ist, dass ich den Inhalt, der bereits in diesem einzelnen Beitrag vorhanden ist, paginieren muss.

Der Zweck dieser Funktionalität bestand darin, Posts zu ermöglichen, benutzerdefinierte Autoren zu haben (außerhalb des eingebauten Benutzersystems), und der Zweck dieser Vorlage besteht darin, alle Posts für einen bestimmten Autor (der bereits funktioniert) auszugeben.

Shane
quelle
3
Eine Aufwertung für eine gut formatierte Frage, obwohl Sie nicht beschrieben haben, warum Sie dies tun, handelt es sich um verwandte Posts des aktuellen Autorenkastens?
Tom J Nowell
1
Ich stimme wirklich mit @TomJNowell überein. +1
Pieter Goosen
2
Nicht verwandt, aber es ist nicht notwendig, Echothe_title()
Pieter Goosen
2
Wird 'meta_value' => $author_idvon der genannten Dropdown-Liste ausgefüllt? Und wenn Sie jeden Autor über das Dropdown-Menü auswählen, werden die ersten zehn Beiträge korrekt angezeigt?
Stephen S.
1
Haben Sie sichergestellt, dass das $author_query->have_posts()zurückkehrt trueund dass das $author_querytatsächlich irgendwelche Beiträge enthält?
Kaiser

Antworten:

17

Du hast 2 Probleme.

Erstes Problem

Die Linie

$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;

wird fehlschlagen, weil in der singulären Post-Ansicht, wenn die URL enthält '/page/XX/', die Variable WordPress gesetzt ist 'page'und nicht 'paged'.

Sie können denken, 'page'statt zu verwenden 'paged', aber das wird auch nicht funktionieren, weil WordPress die Anfrage umleiten wird , sobald die 'page'Variable für mehrseitige singuläre Posts (Seitentrennung mit <!--nextpage-->) verwendet werden soll und sobald der Post nicht mehrseitig ist zur URL ohne '/page/XX/'.

Dies passiert, wenn Sie Ihre Abfragevariable benennen $wp_query.

Die Lösung besteht darin, diese Umleitung zu verhindern, indem die dafür verantwortliche Funktion entfernt wird, die 'redirect_canonical'verknüpft ist mit 'template_redirect':

Also, in Ihrem functions.phphinzufügen:

add_action( 'template_redirect', function() {
    if ( is_singular( 'authors' ) ) {
        global $wp_query;
        $page = ( int ) $wp_query->get( 'page' );
        if ( $page > 1 ) {
            // convert 'page' to 'paged'
            $wp_query->set( 'page', 1 );
            $wp_query->set( 'paged', $page );
        }
        // prevent redirect
        remove_action( 'template_redirect', 'redirect_canonical' );
    }
}, 0 ); // on priority 0 to remove 'redirect_canonical' added with priority 10

Jetzt leitet WordPress nicht mehr weiter und setzt die 'paged'Abfragevariable korrekt .

Zweites Problem

next_posts_link()und previous_posts_link()beide prüfen if ( ! is_single() ), um die Paginierung anzuzeigen.

Dies is_single()ist in Ihrem Fall der Fall, da Sie sich in einem einzelnen Beitrag vom Typ "Autor" befinden, sodass diese Funktionen nicht wie erwartet funktionieren können.

Sie haben 3 Möglichkeiten:

  1. Verwenden Sie query_postsdiese Option, um die Hauptabfrage zu überschreiben (wirklich nicht empfohlen).
  2. Verwenden Sie eine benutzerdefinierte Seitenvorlage anstelle eines benutzerdefinierten Beitragstyps, da diese is_single()für Seiten falsch ist und Ihr Code dort funktioniert.
  3. Schreiben Sie Ihre eigene Paginierungsfunktion und verwenden Sie diese

Das ist der Code für die Lösung Nr. 3:

function my_pagination_link( $label = NULL, $dir = 'next', WP_Query $query = NULL ) {
    if ( is_null( $query ) ) {
        $query = $GLOBALS['wp_query'];
    }
    $max_page = ( int ) $query->max_num_pages;
    // only one page for the query, do nothing
    if ( $max_page <= 1 ) {
        return;
    }
    $paged = ( int ) $query->get( 'paged' );
    if ( empty( $paged ) ) {
        $paged = 1;
    }
    $target_page = $dir === 'next' ?  $paged + 1 : $paged - 1;
    // if 1st page requiring previous or last page requiring next, do nothing
    if ( $target_page < 1 || $target_page > $max_page ) {
        return;
    }
    if ( null === $label ) {
        $label = __( 'Next Page &raquo;' );
    }

    $label = preg_replace( '/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label );
    printf( '<a href="%s">%s</a>', get_pagenum_link( $target_page ), esc_html( $label ) );
}

und benutze es wie folgt single-authors.php:

my_pagination_link( 'Older Entries', 'next', $author_query );
my_pagination_link( 'Newer Entries', 'prev', $author_query );
gmazzap
quelle
Sehr ausführliche Antwort, danke! Dies funktioniert für die englische Seite der Site, aber auf der französischen Seite bewirken die Paginierungslinks nichts, sie aktualisieren nur die Seite. Ich benutze WPML.
Shane
1
@Shane scheint also, dass WPML einen Filter ausführt, der verhindert, dass Code funktioniert. Aber ist ein so großes Plugin, und so kann ich nicht Tausende von Codezeilen graben, um zu verstehen, wo der Konflikt ist. Fragen Sie den WPML-Support.
gmazzap
@Shane Die WPML-Support-Foren - und wenn oben funktioniert (was ich vermute ), dann markieren Sie es bitte als Lösung. Der WPML-Konflikt ist ohnehin ein Thema, das nicht in den Geltungsbereich dieser Website fällt.
Kaiser
Fantastische Antwort, hauptsächlich, weil es mir geholfen hat, mein Paginierungsproblem zu beheben. Ich habe eine ähnliche Aufgabe ausgeführt und eine zweite WP_Query erstellt, um eine Schleife durchzuführen. Ich rief an the_posts_pagination, musste aber eine Kopie der ursprünglichen wp_query nehmen, wie in dieser Frage beschrieben: wordpress.stackexchange.com/questions/216821/…
Alexander Holsgrove
1
Du hast recht @HongPong, behoben, danke.
gmazzap
0

Basierend auf einer ähnlichen WPSE-Frage "Die Paginierung funktioniert nicht mit benutzerdefinierten Feldwerten für wp_query " würde ich vorschlagen global $paged;, am Anfang Ihrer Vorlagendatei Folgendes hinzuzufügen :

global $paged;
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
Stephen S.
quelle
1
Danke für die Antwort! Leider scheint es keinen Unterschied zu machen. Die Links zur Paginierung werden nicht angezeigt
Shane
1
Stephen, warum sollte das helfen? Ja, das würde es aus dem globalen Kontext bringen, aber bisher machen Sie nichts damit. Wenn Sie die globale überschreiben möchten, verwenden Sie $GLOBALS['paged'] = get_query_var( 'paged' );. Andernfalls verwenden Sie einfach den globalen Inhalt.
Kaiser
@Shane Hmm, wird die Vorlagenseite als statische Startseite verwendet?
Stephen S.
Nein, es wird nur als einzelne Beitragsvorlage für den benutzerdefinierten Beitragstyp verwendet. Ich habe versucht, meine Abfrage von auf $author_queryzu ändern , $wp_queryund dies schien die Paginierung erscheinen zu lassen, aber wenn ich darauf klicke, wird die Seite aktualisiert und tatsächlich nicht zur nächsten Seite gewechselt , obwohl es mehrere Seiten gibt. Ich habe meine Antwort aktualisiert, um diese Änderungen widerzuspiegeln.
Shane
1
Die php.net Erklärung ist nicht so schlecht. Ich würde vorschlagen, nur mit globalund herumzuspielen $GLOBALS. Ein bisschen var_dump(), einige Funktionen und es geht dir gut. Um es mit ein wenig Versuch / Irrtum wirklich zu verstehen, werden Sie ca. brauche eine halbe Stunde. Auf diese Weise können Sie Funktionen im Vergleich zu Klassen und den OOP-Ansatz insgesamt besser verstehen. Und es wird Sie dem Verständnis von Namespaces deutlich näher bringen :)
Kaiser