Pagination WP_Query sur single-custom.php

16

Ce que je cherche à faire:

Configuration de la WP_Querypagination dans un fichier de modèle single-custom-post-type.php

Ce que j'ai fait

1) Création d'un type de publication appelé "auteurs". Chaque article de ce type d'article est un auteur individuel.

2) Les pages d'écran de publication standard contiennent une liste déroulante qui répertorie toutes les publications (auteurs) du type de publication personnalisé des auteurs.

3) Création d'un modèle single-authors.php qui interroge tous les messages avec les métadonnées de l'auteur dans la liste déroulante, donc le résultat est une liste de messages auxquels le même auteur leur est affecté (un peu comme une archive):

<?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();
?>

Sur quoi je suis coincé

Les liens de pagination n'apparaissent pas. J'ai fait quelques recherches et j'ai découvert qu'ils utilisent la $wp_queryvariable, cependant quand j'ai changé ma variable de requête en $wp_query, les liens sont apparus, mais quand on a cliqué n'a rien fait.

Une idée où je me trompe?

Éditer:

Pour répondre à certaines de vos questions, ma requête génère avec succès les messages que j'interroge, $ author_id a déjà une valeur que je n'ai pas incluse dans cet extrait de code. De même, j'ai omis la sortie de contenu réelle dans la boucle while car cette partie n'est pas le problème. Le problème est que je dois paginer le contenu qui existe déjà sur ce seul post.

Le but de cette fonctionnalité était de permettre aux publications d'avoir des auteurs personnalisés (en dehors du système intégré des utilisateurs) et le but de ce modèle est de générer toutes les publications d'un auteur donné (qui fonctionne déjà).

Shane
la source
3
Un vote positif pour une question bien formatée, bien que vous n'ayez pas décrit pourquoi vous faites cela, est-ce un message connexe de la boîte d'auteur actuelle?
Tom J Nowell
1
Je suis vraiment d'accord avec @TomJNowell. +1
Pieter Goosen
2
Sans rapport, mais il n'est pas nécessaire de faire échothe_title()
Pieter Goosen
2
Est-ce 'meta_value' => $author_idque le menu déroulant est rempli? Et lors de la sélection de chaque auteur via la liste déroulante, les dix premiers articles s'affichent-ils correctement?
Stephen S.
1
Vous êtes-vous assuré que les $author_query->have_posts()retours trueet que le $author_querycontient effectivement des messages?
kaiser

Réponses:

17

Vous avez 2 problèmes.

Premier problème

La ligne

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

échouera, car en vue de publication unique, lorsque l'URL contient '/page/XX/', la variable WordPress définit est 'page'et non 'paged'.

Vous pouvez penser à utiliser à la 'page'place de 'paged', mais cela ne fonctionnera pas non plus, car une fois que la 'page'variable est destinée à être utilisée pour une publication singulière de plusieurs pages (séparation de page à l'aide <!--nextpage-->) et une fois que la publication n'est pas multi-page, WordPress redirigera la demande à l'URL sans '/page/XX/'.

C'est ce qui se produit lorsque vous nommez votre variable de requête $wp_query.

La solution est d'empêcher cette redirection en supprimant la fonction qui en est responsable, qui est 'redirect_canonical'connectée à 'template_redirect':

Donc, dans votre functions.phpajout:

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

Maintenant, WordPress ne redirigera plus et définira correctement la 'paged'requête var.

Deuxième problème

next_posts_link()et les previous_posts_link()deux vérifient if ( ! is_single() )pour afficher la pagination.

Maintenant, is_single()c'est vrai dans votre cas, parce que vous êtes dans un seul poste de type "auteur", donc ces fonctions ne peuvent pas fonctionner comme prévu.

Vous avez 3 possibilités:

  1. Utilisez query_postspour remplacer la requête principale (vraiment pas recommandé)
  2. Utilisez un modèle de page personnalisé au lieu d'un type de publication personnalisé, car il is_single()est faux pour les pages, et votre code y fonctionnera.
  3. Écrivez votre propre fonction de pagination et utilisez-la

C'est le code de la solution numéro 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 ) );
}

et l'utiliser comme ça dans single-authors.php:

my_pagination_link( 'Older Entries', 'next', $author_query );
my_pagination_link( 'Newer Entries', 'prev', $author_query );
gmazzap
la source
Réponse très détaillée, merci! Cela fonctionne pour le côté anglais du site, mais du côté français, les liens de pagination ne font rien, ils rafraîchissent seulement la page. J'utilise WPML.
Shane
1
@Shane semble donc que WPML exécute un filtre qui empêche le code de fonctionner. Mais c'est un gros plugin, et donc je ne peux pas creuser des milliers de lignes de code pour comprendre où est le conflit. Essayez de demander le support WPML.
gmazzap
@Shane Les forums de support WPML - et si ci-dessus fonctionne pour (ce que je suppose), veuillez le marquer comme solution. Le conflit WPML est hors sujet / hors de portée de toute façon.
kaiser
Une réponse fantastique, principalement parce qu'elle m'a aidé à résoudre mon problème de pagination. J'ai fait une tâche similaire et j'ai créé un deuxième WP_Query à boucler. J'ai appelé the_posts_paginationmais j'ai dû prendre une copie de l'original wp_query comme indiqué dans cette question: wordpress.stackexchange.com/questions/216821/…
Alexander Holsgrove
1
Vous avez raison @HongPong, corrigé, merci.
gmazzap
0

Sur la base d'une autre question WPSE similaire " La pagination ne fonctionne pas avec les valeurs des champs personnalisés wp_query ", je suggère d'ajouter global $paged;au début de votre fichier de modèle:

global $paged;
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
Stephen S.
la source
1
Merci pour la réponse! Malheureusement, cela ne semble faire aucune différence. Les liens de pagination n'apparaissent pas
Shane
1
Stephen, pourquoi cela devrait-il aider? Oui, cela le ramènerait du contexte mondial, mais jusqu'à présent, vous ne faites rien avec. Si vous souhaitez remplacer le global, utilisez $GLOBALS['paged'] = get_query_var( 'paged' );. Sinon, utilisez simplement le contenu global.
kaiser
@Shane Hmm, la page de modèle est-elle utilisée comme première page statique?
Stephen S.
Non, il n'est utilisé que comme modèle de publication unique pour le type de publication personnalisé. J'ai essayé de changer ma requête de $author_queryà $wp_queryet cela semblait faire apparaître la pagination, mais quand je clique dessus, la page s'actualise et ne passe pas réellement à la page suivante, même s'il y a plusieurs pages. J'ai mis à jour ma réponse pour refléter ces changements.
Shane
1
L' explication de php.net n'est pas si mauvaise. Je suggère simplement de jouer avec globalet $GLOBALS. Un peu de var_dump(), quelques fonctions et ça va. Pour vraiment le comprendre avec un peu d'essais / erreurs, vous aurez env. besoin d'une demi-heure. Cela vous aidera à mieux comprendre les fonctions par rapport aux classes et l'approche OOP dans son ensemble. Et cela vous rapprochera clairement de la compréhension des espaces de noms :)
kaiser