Autonomía digital y tecnológica

Código e ideas para una internet distribuida

Entendiendo el sistema de paginación de WordPress: paginando el archivo, los resultados de búsqueda o un custom post type

Imago voragine.net

La función que ofrece WordPress para introducir una barra con enlaces a las diferentes páginas de resultados es paginate_links, es decir, un paginador de resultados del tipo «Anterior, 1, 2, 3, …, Siguiente».

Esta función se encarga de construir las URLs para cada página de resultados, y es eficaz, salvo si entran en juego otros parámetros en la URL, por ejemplo s si queremos paginar los resultados de una búsqueda o post_type si estamos paginando un loop para un post type diferente a post. En estos casos, tendremos que ayudar a paginate_links a construir las URLs.

Para ello tenemos que darle a WordPress la siguiente información:

  • El loop a paginar.
  • El número total de páginas, en función de la cantidad de posts en el loop y la página actual en la que se está.
  • Los parámetros de la URL que queremos mantener en los enlaces a las distintas páginas.

Consideraciones iniciales sobre los parámetros de la URL

Para ver cómo funciona la construcción de las URLs de paginación vamos a suponer que queremos paginar los resultados de una búsqueda limitada a un único post type, por ejemplo un custom post type llamado noticia, y que además estamos usando pretty permalinks de WordPress.

La búsqueda de WordPress funciona pasando como parámetro por la URL la query de búsqueda que un usuario introduce en el formulario. Si además la búsqueda está limitada a un único post type, los parámetros que integran la URL para una búsqueda de este tipo son s, que contiene la query buscada, y post_type, que contiene el tipo de post al que queremos limitar la búsqueda. Las URLs tendrán este aspecto:

http://example.net/?s=busqueda&post_type=noticia

La paginación en WordPress se controla igualmente pasando otra variable por la URL: para acceder a las distintas páginas de este loop lo único que tenemos que hacer es añadir el parámetro paged a la URL, y asignarle el valor de la página. Para ver la segunda página de resultados, por ejemplo:

http://example.net/?s=busqueda&post_type=noticia&paged=2

Definiendo el loop a paginar y los parámetros de paginación

Si no hemos definido un loop personalizado, el loop de WordPress se guarda en la variable $wp_query. Es aquí donde se guardan también el número total de páginas del loop, que permite saber a WordPress cuántos enlaces tiene que construir, y la página actual (current) que se está visitando:

$wp_query->query_vars['paged'] > 1 ? $current = $wp_query->query_vars['paged'] : $current = 1;
$total = $wp_query->max_num_pages;

Construyendo las URLs de la paginación con paginate_links

La función paginate_links es la que construye los enlaces a las diferentes páginas, basta suministrarle los parámetros adecuados: en el ejemplo siguiente, y en orden, el número total de páginas (total) y la página actual (current), ambos obtenidos de $wp_query; y el tipo de salida de la función (type), que aquí definimos como «list» y que produce una lista HTML tipo «ul».

$pag_args = array(
        'total' => $total,
        'current' => $current,
        'type' => 'list',
);
$pags_list = paginate_links($pag_args);
echo $pags_list;

En la documentación de paginate_link se pueden consultar todos los parámetros para variar la salida de la función: número de enlaces a mostrar, texto para el enlace «anterior» y «siguiente»…

Con este código ya tenemos nuestra paginación. Ahora vamos a ver cómo personalizar la salida para adaptarla a nuestro caso particular: búsqueda limitada a un único post type.

Modificando la salida de paginate_links para adaptarla a nuestro loop: añadiendo y eliminando parámetros

paginate_links construye las URLs de paginación de la siguiente manera: como base por omisión utiliza la URL de la página actual; como ésta contiene el parámetro paged con el valor de página actual, lo elimina de la URL, y luego le añade el parámetro paged con el valor correspondiente en cada enlace. Por ejemplo, si estamos en la página 2 la base para paginate_links será:

http://example.net/?paged=2

El problema en nuestro caso es que paginate_links elimina todos los parámetros de la URL, no solo paged. paginate_links permite definir la base de la URL mediante el argumento base, que es el que vamos a usar para definirla según nuestras necesidades. Para ello tenemos que deconstruir la URL, eliminar el parámetro paged y añadir los que construyen el loop, s y post_type, y de nuevo paged, con valor variable según el enlace.

La función remove_query_arg permite eliminar parámetros de la URL pero en algunos casos a mí no me funciona, por ejemplo para eliminar paged. Para ello se puede usar también una búsqueda con sustitución de PHP con preg_replace:

// obtenemos la URL actual
$url_raw = "http://" .$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
// eliminamos el parámetro paged
$url_raw = preg_replace('/\/page\/[0-9]*/','',$url_raw);
// obtenemos el parámetro post_type
$pt_current = sanitize_text_field( $_GET['post_type'] );
// construimos la URL
$pag_args['base'] = user_trailingslashit( trailingslashit( remove_query_arg(array('s','post_type'),$url_raw)). "page/%#%/", 'paged'). "?s=" .get_query_var('s'). "&post_type=" .$pt_current;

Con esto ya tenemos definida la base de las URL. A continuación el código completo, con todas las partes que hemos visto:

global $wp_rewrite;

$wp_query->query_vars['paged'] > 1 ? $current = $wp_query->query_vars['paged'] : $current = 1;
$total = $wp_query->max_num_pages;

$pag_args = array(
        'total' => $total,
        'current' => $current,
        'type' => 'list',
);

if( $wp_rewrite->using_permalinks() ) { // if pretty permalinks

   // obtenemos la URL actual
   $url_raw = "http://" .$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
   // eliminamos el parámetro paged
   $url_raw = preg_replace('/\/page\/[0-9]*/','',$url_raw);
   // obtenemos el parámetro post_type
   $pt_current = sanitize_text_field( $_GET['post_type'] );
   // construimos la URL
   $pag_args['base'] = user_trailingslashit( trailingslashit( remove_query_arg(array('s','post_type'),$url_raw)). "page/%#%/", 'paged'). "?s=" .get_query_var('s'). "&post_type=" .$pt_current;

} // end if pretty permalink

$pags_list = paginate_links($pag_args);
echo $pags_list;

2 comentarios

Dejar un comentario

*
*

 

2 trackbacks