Cómo mostrar enlaces de paginación para WP_User_Query
Creo que estoy cerca de conseguirlo, pero no logro que se muestren los enlaces de paginación para un directorio de autores que estoy creando.
Mi código está abajo, pero no sé cómo hacer que funcionen los enlaces para navegar entre las páginas de autores. ¿Alguien puede ayudarme? Tengo la sensación de que esto podría ser útil, pero no sé cómo implementarlo:
Gracias
Osu
<?php
/* ****************************************************************** */
/* !LISTAR AUTORES */
/* ****************************************************************** */
// AGRADECIMIENTOS A:
// http://www.mattvarone.com/wordpress/list-users-with-wp_user_query/
// paginación
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1; // Necesario para la paginación
$paged -= 1;
$limit = 2;
$offset = $paged * $limit;
// preparar argumentos
$args = array(
// buscar solo por rol de Autor
'role' => 'Subscriber',
// ordenar resultados por display_name
'orderby' => 'display_name',
// devolver todos los campos
'fields' => 'all_with_meta',
'number' => $limit,
'offset' => $offset
);
// Crear el objeto WP_User_Query
$wp_user_query = new WP_User_Query($args);
// Obtener los resultados
$authors = $wp_user_query->get_results();
// Comprobar si hay resultados
if (!empty($authors))
{
echo '<div class="author-entry">';
// recorrer cada autor
foreach ($authors as $author)
{
$author_info = get_userdata($author->ID); ?>
<span style="float:left;padding:0 5px 0 0;"><?php echo get_avatar( $author->ID, 50 ); /* http://codex.wordpress.org/Function_Reference/get_avatar */ ?></span>
<span class="fn"><strong>Nombre</strong> : <?php echo $author_info->first_name; ?></span><br />
<span class="ln"><strong>Apellido</strong> : <?php echo $author_info->last_name; ?></span><br />
<span class="em"><strong>Correo electrónico</strong> : <a href="mailto:<?php echo $author_info->user_email; ?>"><?php echo $author_info->user_email; ?></a></span><br />
<span class="we"><strong>Sitio web</strong> : <a href="<?php echo $author_info->user_url; ?>"><?php echo $author_info->user_url; ?></a></span><br />
<span class="de"><strong>Biografía</strong> :<br /><?php echo $author_info->description ; ?></span>
<div class="clear"> </div>
<?php
}
echo '</div>';
} else {
echo 'No se encontraron autores';
}
?>
<?php /* ¿QUÉ PONGO AQUÍ PARA CREAR LOS ENLACES DE PAGINACIÓN? */ ?>

Esto debería acercarte mucho a lo que necesitas. No lo he probado, pero es casi idéntico a una configuración que he usado varias veces.
/*
* Comenzamos haciendo una consulta para recuperar todos los usuarios
* Necesitamos un conteo total de usuarios para poder calcular cuántas páginas hay
*/
$count_args = array(
'role' => 'Subscriber', // Rol: Suscriptor
'fields' => 'all_with_meta', // Todos los campos con metadatos
'number' => 999999 // Número arbitrariamente grande para obtener todos
);
$user_count_query = new WP_User_Query($count_args);
$user_count = $user_count_query->get_results();
// Contamos el número de usuarios encontrados en la consulta
$total_users = $user_count ? count($user_count) : 1;
// Obtenemos el número de página actual y lo establecemos en 1 si no está definido
$page = isset($_GET['p']) ? $_GET['p'] : 1;
// Cuántos usuarios mostrar por página
$users_per_page = 5;
// Calculamos el número total de páginas
$total_pages = 1;
$offset = $users_per_page * ($page - 1);
$total_pages = ceil($total_users / $users_per_page);
// Consulta principal de usuarios
$args = array(
// Buscar solo el rol de Suscriptor
'role' => 'Subscriber',
// Ordenar resultados por nombre para mostrar
'orderby' => 'display_name',
// Devolver todos los campos
'fields' => 'all_with_meta',
'number' => $users_per_page,
'offset' => $offset // Saltar el número de usuarios que tenemos por página
);
// Creamos el objeto WP_User_Query
$wp_user_query = new WP_User_Query($args);
// Obtenemos los resultados
$authors = $wp_user_query->get_results();
// Verificamos si tenemos usuarios
if (!empty($authors))
{
echo '<div class="author-entry">';
// Recorremos cada autor
foreach ($authors as $author)
{
$author_info = get_userdata($author->ID); ?>
<span style="float:left;padding:0 5px 0 0;"><?php echo get_avatar( $author->ID, 50 ); /* http://codex.wordpress.org/Function_Reference/get_avatar */ ?></span>
<span class="fn"><strong>Nombre</strong> : <?php echo $author_info->first_name; ?></span><br />
<span class="ln"><strong>Apellido</strong> : <?php echo $author_info->last_name; ?></span><br />
<span class="em"><strong>Correo electrónico</strong> : <a href="mailto:<?php echo $author_info->user_email; ?>"><?php echo $author_info->user_email; ?></a></span><br />
<span class="we"><strong>Sitio web</strong> : <a href="<?php echo $author_info->user_url; ?>"><?php echo $author_info->user_url; ?></a></span><br />
<span class="de"><strong>Biografía</strong> :<br /><?php echo $author_info->description ; ?></span>
<div class="clear"> </div>
<?php
}
echo '</div>';
} else {
echo 'No se encontraron autores';
}
// Obtenemos los parámetros actuales de la consulta
$query_string = $_SERVER['QUERY_STRING'];
// La variable $base almacena la URL completa a nuestra página, incluyendo el argumento de página actual
// Si estamos en el admin, la base debe ser la URL de admin + tu página
$base = admin_url('your-page-path') . '?' . remove_query_arg('p', $query_string) . '%_%';
// Si está en el frontend, tu base es la página actual
//$base = get_permalink( get_the_ID() ) . '?' . remove_query_arg('p', $query_string) . '%_%';
echo paginate_links( array(
'base' => $base, // La URL base, incluyendo argumentos de consulta
'format' => '&p=%#%', // Define el parámetro de consulta que se usará, en este caso "p"
'prev_text' => __('« Anterior'), // Texto para página anterior
'next_text' => __('Siguiente »'), // Texto para página siguiente
'total' => $total_pages, // El número total de páginas que tenemos
'current' => $page, // La página actual
'end_size' => 1,
'mid_size' => 5,
));

Gracias por esto @Pippin, lo probaré cuando llegue al estudio. Una pregunta: ¿qué pongo en la parte 'your-page-path' del admin_url? ¿Es la raíz de mi sitio?

¿La página que muestra a tus usuarios está en el administrador o en la parte pública del sitio?

Hola @Pippin, es en la parte pública, pero me interesaba saber para qué servía esa parte del código :)

Esa parte del código es necesaria para generar los enlaces de paginación. La función paginate_links() necesita saber a qué URL añadir los argumentos de consulta. Simplemente te di un ejemplo para el administrador y otro para la parte pública, pero puedes ignorar la versión del administrador.

Me encanta este código. Una plantilla completamente funcional ;) muchas gracias. Para aquellos que copien y peguen (y quizás lo editen) - la variable $limit necesita cambiarse por $users_per_page. Supongo que se perdió cuando se agregaron las explicaciones.

Enfoque interesante. Noté que estás ejecutando 2 consultas aquí: la primera para obtener todos los usuarios y la segunda para obtener solo los usuarios de la página correspondiente. ¿No tendría mejor rendimiento si usaras solo 1 consulta y luego usaras array_slice para dividir los resultados en páginas? Parece que, dado que estás realizando 2 consultas diferentes sobre los mismos datos, podrías ahorrar algo de rendimiento eliminando una.

Realmente no deberías usar la respuesta de Pippin. La consulta es muy ineficiente. $user_count_query
en el ejemplo puede devolver hasta 999,999 usuarios de tu base de datos a tu script, con todos los campos de usuario. Esto seguramente alcanzará los límites de memoria y/o tiempo de PHP si/cuando tu sitio crezca lo suficiente.
Pero puede que esa haya sido la única solución en 2012.
Aquí hay una mejor manera de hacerlo. En este ejemplo solo tengo página siguiente y anterior pero si necesitas paginación numerada, las variables están ahí para construirla. WordPress no tiene una función de paginación compatible con WP_User_Query (que yo sepa).
<?php
// Variables de paginación
$current_page = get_query_var('paged') ? (int) get_query_var('paged') : 1;
$users_per_page = 2; // AUMENTA ESTO DESPUÉS DE PROBAR ;)
$args = array(
'number' => $users_per_page, // Cuántos por página
'paged' => $current_page // Qué página obtener, comenzando desde 1.
);
$users = new WP_User_Query( $args );
$total_users = $users->get_total(); // Cuántos usuarios tenemos en total (más allá de la página actual)
$num_pages = ceil($total_users / $users_per_page); // Cuántas páginas de usuarios necesitaremos
?>
<h3>Página <?php echo $current_page; ?> de <?php echo $num_pages; ?></h3>
<p>Mostrando <?php echo $users_per_page; ?> de <?php echo $total_users; ?> usuarios</p>
<table>
<thead>
<tr>
<th>Nombre</th>
<th>Apellido</th>
<th>Correo electrónico</th>
</tr>
</thead>
<tbody>
<?php
if ( $users->get_results() ) foreach( $users->get_results() as $user ) {
$firstname = $user->first_name;
$lastname = $user->last_name;
$email = $user->user_email;
?>
<tr>
<td><?php echo esc_html($firstname); ?></td>
<td><?php echo esc_html($lastname); ?></td>
<td><?php echo esc_html($email); ?></td>
</tr>
<?php
}
?>
</tbody>
</table>
<p>
<?php
// Página anterior
if ( $current_page > 1 ) {
echo '<a href="'. add_query_arg(array('paged' => $current_page-1)) .'">Página Anterior</a>';
}
// Página siguiente
if ( $current_page < $num_pages ) {
echo '<a href="'. add_query_arg(array('paged' => $current_page+1)) .'">Página Siguiente</a>';
}
?>
</p>
Ejemplo mostrando página 2:
Actualización 8/6/2018: Cómo añadir números de página en lugar de Siguiente/Anterior
Si quieres tener números de página en lugar de enlaces de página siguiente/anterior, aquí está cómo puedes configurarlo. Ten en cuenta que necesitarás reemplazar los números con enlaces de página, no serán clickeables en este ejemplo (basado en https://stackoverflow.com/a/11274294/470480, modificado para mostrar una cantidad consistente de números intermedios y no añadir "..." a menos que se salte una página).
También puedes ver mi archivo gist que contiene una función reusable para este propósito.
$current_page = 5; // Ejemplo
$num_pages = 10; // Ejemplo
$edge_number_count = 2; // Cambia esto, opcional
$start_number = $current_page - $edge_number_count;
$end_number = $current_page + $edge_number_count;
// Menos uno para no dividir el número inicial innecesariamente, ej: "1 ... 2 3" debería empezar como "1 2 3"
if ( ($start_number - 1) < 1 ) {
$start_number = 1;
$end_number = min($num_pages, $start_number + ($edge_number_count*2));
}
// Más uno para no dividir el número final innecesariamente, ej: "8 9 ... 10" debería permanecer como "8 9 10"
if ( ($end_number + 1) > $num_pages ) {
$end_number = $num_pages;
$start_number = max(1, $num_pages - ($edge_number_count*2));
}
if ($start_number > 1) echo " 1 ... ";
for($i=$start_number; $i<=$end_number; $i++) {
if ( $i === $current_page ) echo " [{$i}] ";
else echo " {$i} ";
}
if ($end_number < $num_pages) echo " ... {$num_pages} ";
Salida (de la página 1 a 10):
[1] 2 3 4 5 ... 10
1 [2] 3 4 5 ... 10
1 2 [3] 4 5 ... 10
1 2 3 [4] 5 ... 10
1 ... 3 4 [5] 6 7 ... 10
1 ... 4 5 [6] 7 8 ... 10
1 ... 6 [7] 8 9 10
1 ... 6 7 [8] 9 10
1 ... 6 7 8 [9] 10
1 ... 6 7 8 9 [10]

Estoy de acuerdo. La respuesta de Pippin requiere 2 consultas a la base de datos, lo cual debería evitarse si es posible.

Hola @radley-sustaire, esta es una gran solución, pero me preguntaba si hay alguna manera de cambiar la parte que dice "mostrando 2 de 6 usuarios" por el rango real de usuarios por página. Algo como "mostrando 1-2 de 6" para la página 1, "3-4 de 6" para la página 2 y "5-6 de 6" para la página 3. Actualmente, solo muestra "2 de 6" para todas las páginas.

@damienoneill2001 Esa es una buena idea, puedes comenzar con algo como: $start_user_num = (($current_page-1) * $users_per_page) + 1;
y $end_user_num = $start_user_num + count($users->get_results());
.

@RadleySustaire excelente, gracias por eso. Al principio, recibí el siguiente error: Call to a member function get_results() on a non-object
así que modifiqué $end_user_number
a $start_user_num + ($users_per_page-1);
y eso resolvió el problema. ¡Gracias de nuevo!

Resulta que hablé demasiado pronto sobre eso. Cuando llego a la página final que no contiene una lista completa de usuarios, obviamente muestra la cifra incorrecta para $end_user_number
en mi solución. ¡De vuelta a la mesa de dibujo, ja!

Todos los créditos deberían ir para @radley-sustaire por su respuesta, pero noté un pequeño error en ella, así que comparto mi versión de la respuesta aquí.
Con mi versión también estaba filtrando resultados por ubicación, palabra clave, etc., por lo que algunas páginas tenían menos resultados que la variable '$users_per_page'. Por ejemplo, si tenía configurado mostrar 10 usuarios por página, pero el filtro solo devolvía 3 usuarios, obtenía "Mostrando 10 de 3 usuarios" en la parte superior de la página. Obviamente esto no tenía sentido, así que agregué una simple declaración "if" para verificar si el conteo de resultados era mayor que la variable '$users_per_page'.
Radley, si editas tu respuesta con esta actualización, con gusto votaré por ella como la respuesta correcta, ya que creo que es mejor que la solución de Pippin.
Así que este es el código final para quien lo necesite.
<?php
// Variables de paginación
$current_page = get_query_var('paged') ? (int) get_query_var('paged') : 1;
$users_per_page = 10;
$args = array(
'number' => $users_per_page, // Cuántos por página
'paged' => $current_page // Qué página obtener, comenzando desde 1.
);
$users = new WP_User_Query( $args );
$total_users = $users->get_total(); // Cuántos usuarios tenemos en total (más allá de la página actual)
$num_pages = ceil($total_users / $users_per_page); // Cuántas páginas de usuarios necesitaremos
if ($total_users < $users_per_page) {$users_per_page = $total_users;}
?>
<h3>Página <?php echo $current_page; ?> de <?php echo $num_pages; ?></h3>
<p>Mostrando <?php echo $users_per_page; ?> de <?php echo $total_users; ?> usuarios</p>
<table>
<thead>
<tr>
<th>Nombre</th>
<th>Apellido</th>
<th>Correo electrónico</th>
</tr>
</thead>
<tbody>
<?php
if ( $users->get_results() ) foreach( $users->get_results() as $user ) {
$firstname = $user->first_name;
$lastname = $user->last_name;
$email = $user->user_email;
?>
<tr>
<td><?php echo esc_html($firstname); ?></td>
<td><?php echo esc_html($lastname); ?></td>
<td><?php echo esc_html($email); ?></td>
</tr>
<?php
}
?>
</tbody>
</table>
<p>
<?php
// Página anterior
if ( $current_page > 1 ) {
echo '<a href="'. add_query_arg(array('paged' => $current_page-1)) .'">Página anterior</a>';
}
// Página siguiente
if ( $current_page < $num_pages ) {
echo '<a href="'. add_query_arg(array('paged' => $current_page+1)) .'">Página siguiente</a>';
}
?>
</p>
