Paginación WP_Query en single-custom.php

16

Lo que estoy buscando hacer:

Configura la WP_Querypaginación en un archivo de plantilla single-custom-post-type.php

Que he hecho

1) Creó un tipo de publicación llamado "autores". Cada publicación dentro de ese tipo de publicación es un autor individual.

2) Las páginas de pantalla de publicación de edición estándar contienen un menú desplegable que enumera todas las publicaciones (autores) del tipo de publicación personalizada de los autores.

3) Creé una plantilla single-author.php que consulta todas las publicaciones con los metadatos del autor en el menú desplegable, por lo que el resultado es una lista de publicaciones que tienen asignado el mismo autor (algo así como un archivo):

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

En lo que estoy atrapado

Los enlaces de paginación no aparecen. Investigué un poco y descubrí que usan la $wp_queryvariable, sin embargo, cuando cambié mi variable de consulta $wp_query, aparecieron los enlaces, pero cuando hice clic no hizo nada.

¿Alguna idea de a dónde me voy

Editar:

Para responder algunas de sus preguntas, mi consulta genera con éxito las publicaciones que estoy consultando, $ author_id ya tiene un valor que no incluí en este fragmento de código. Del mismo modo, omití la salida de contenido real dentro del ciclo while porque esa parte no es el problema. El problema es que necesito paginar el contenido que ya existe en esta publicación.

El propósito de esta funcionalidad era permitir que las publicaciones tuvieran autores personalizados (fuera del sistema de usuarios incorporado) y el propósito de esta plantilla es generar todas las publicaciones para un autor determinado (que ya está funcionando).

Shane
fuente
3
Un voto a favor para una pregunta bien formateada, aunque no describió por qué está haciendo esto, ¿es una publicación relacionada del cuadro del autor actual?
Tom J Nowell
1
Realmente estoy de acuerdo con @TomJNowell. +1
Pieter Goosen
2
Sin relación, pero no es necesario hacer ecothe_title()
Pieter Goosen
2
¿Se 'meta_value' => $author_idestá rellenando desde el menú desplegable mencionado? Y al seleccionar cada autor a través del menú desplegable, ¿se muestran correctamente las primeras diez publicaciones?
Stephen S.
1
¿Te has asegurado de que $author_query->have_posts()regrese truey de que $author_queryrealmente contenga alguna publicación?
Kaiser

Respuestas:

17

Tienes 2 problemas

Primer problema

La línea

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

fallará, porque en la vista de publicación singular, cuando la URL contiene '/page/XX/', la variable que establece WordPress es 'page'y no 'paged'.

Puede pensar en usar en 'page'lugar de 'paged', pero eso tampoco funcionará, porque una vez que la 'page'variable está destinada a usarse para publicaciones singulares de varias páginas (separación de páginas usando <!--nextpage-->) y una vez que la publicación no es de varias páginas, WordPress redirigirá la solicitud a la URL sin '/page/XX/'.

Esto es lo que sucede cuando nombra su variable de consulta $wp_query.

La solución es evitar esa redirección eliminando la función responsable de la misma, que está 'redirect_canonical'enganchada en 'template_redirect':

Entonces, en su functions.phpcomplemento:

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

Ahora WordPress ya no redirigirá y configurará correctamente la 'paged'consulta var.

Segundo problema

next_posts_link()y previous_posts_link()ambos verifican if ( ! is_single() )para mostrar la paginación.

Ahora, is_single()es cierto en su caso, porque está en una sola publicación de tipo 'autor', por lo que esas funciones no pueden funcionar como espera.

Tienes 3 posibilidades:

  1. Use query_postspara anular la consulta principal (realmente no se recomienda)
  2. Use una plantilla de página personalizada en lugar de un tipo de publicación personalizada, porque is_single()es falso para las páginas, y su código funcionará allí.
  3. Escribe tu propia función de paginación y úsala

Ese es el código para la solución número 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 ) );
}

y úsalo así en single-authors.php:

my_pagination_link( 'Older Entries', 'next', $author_query );
my_pagination_link( 'Newer Entries', 'prev', $author_query );
gmazzap
fuente
Respuesta muy detallada, gracias! Esto funciona para el lado inglés del sitio, pero en el lado francés los enlaces de paginación no hacen nada, solo actualizan la página. Estoy usando WPML.
Shane
1
@Shane parece que WPML ejecuta un filtro que impide que el código funcione. Pero es un complemento tan grande, por lo que no puedo cavar miles de líneas de código para entender dónde está el conflicto. Intenta pedir ayuda a WPML.
gmazzap
@Shane Los foros de soporte de WPML , y si lo anterior funciona (lo cual supongo), márquelo como solución. El conflicto WPML está fuera del tema / fuera del alcance de este sitio de todos modos.
Kaiser
Fantástica respuesta, principalmente porque me ayudó a solucionar mi problema de paginación. He estado haciendo una tarea similar y he creado una segunda WP_Query para recorrer. Llamé the_posts_paginationpero tuve que tomar una copia del wp_query original como se describe en esta pregunta: wordpress.stackexchange.com/questions/216821/…
Alexander Holsgrove
1
Tienes razón @HongPong, arreglado, gracias.
gmazzap
0

Basado en otra pregunta similar de WPSE "La paginación no funciona con los valores de los campos personalizados wp_query ", sugeriría agregar global $paged;al comienzo de su archivo de plantilla:

global $paged;
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
Stephen S.
fuente
1
¡Gracias por la respuesta! Lamentablemente, no parece hacer ninguna diferencia. Los enlaces de paginación no aparecen
Shane
1
Stephen, ¿por qué debería ayudar eso? Sí, esto lo traerá desde el contexto global, pero hasta ahora no está haciendo nada con él. Si desea anular el global, use $GLOBALS['paged'] = get_query_var( 'paged' );. De lo contrario, solo use el contenido global.
Kaiser
@ Shane Hmm, ¿se está utilizando la página de la plantilla como portada estática?
Stephen S.
No, solo se usa como una plantilla de publicación única para el tipo de publicación personalizada. Intenté cambiar mi consulta de $author_querya $wp_queryy eso pareció hacer aparecer la paginación, pero cuando hago clic en ella, la página se actualiza y en realidad no pasa a la página siguiente, a pesar de que hay varias páginas. He actualizado mi respuesta para reflejar esos cambios.
Shane
1
La explicación de php.net no es tan mala. Sugeriría simplemente jugar con globaly $GLOBALS. Un poco de var_dump(), algunas funciones y estás bien. Para entenderlo realmente con un poco de prueba / error, usted tendrá aprox. Necesito media hora. Esto lo ayudará a comprender mucho mejor las funciones frente a las clases y el enfoque OOP en general. Y claramente te acercará a comprender los espacios de nombres :)
kaiser