Как отобразить пагинацию для WP_User_Query?

4 июл. 2012 г., 16:42:37
Просмотры: 18.8K
Голосов: 11

Я почти добился нужного результата, но не могу заставить работать ссылки пагинации для списка авторов, который я создаю.

Мой код приведен ниже, но я не знаю, как сделать рабочие ссылки для навигации между страницами с авторами. Может кто-нибудь помочь? У меня есть ощущение, что это может пригодиться, но я не знаю, как это реализовать:

paginate_links()

Спасибо,

Osu

    <?php 
/* ****************************************************************** */
                        /* !СПИСОК АВТОРОВ */
/* ****************************************************************** */ 

// БЛАГОДАРНОСТИ:
// http://www.mattvarone.com/wordpress/list-users-with-wp_user_query/

// пагинация
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1; // Необходимо для пагинации
$paged -= 1;
$limit = 2;
$offset = $paged * $limit;

// подготовка аргументов
$args  = array(
    // поиск только для роли Subscriber
    'role'      => 'Subscriber',
    // сортировка по display_name
    'orderby'   => 'display_name',
    // возвращаем все поля
    'fields'    => 'all_with_meta',
    'number'    => $limit,
    'offset'    => $offset      
);
// Создаем объект WP_User_Query
$wp_user_query = new WP_User_Query($args);
// Получаем результаты
$authors = $wp_user_query->get_results();
// Проверяем наличие результатов
if (!empty($authors))
{
    echo '<div class="author-entry">';
    // цикл по каждому автору
    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>Имя</strong> : <?php echo $author_info->first_name; ?></span><br />
        <span class="ln"><strong>Фамилия</strong> : <?php echo $author_info->last_name; ?></span><br />
        <span class="em"><strong>Email</strong> : <a href="mailto:<?php echo $author_info->user_email; ?>"><?php echo $author_info->user_email; ?></a></span><br />
        <span class="we"><strong>Сайт</strong> : <a href="<?php echo $author_info->user_url; ?>"><?php echo $author_info->user_url; ?></a></span><br />

        <span class="de"><strong>Биография</strong> :<br /><?php echo $author_info->description ; ?></span>
        <div class="clear">&nbsp;</div>

    <?php 
    }
    echo '</div>';
} else {
    echo 'Авторы не найдены';
}
?>

<?php /* ЧТО Я ДОЛЖЕН ВСТАВИТЬ ЗДЕСЬ ДЛЯ СОЗДАНИЯ ССЫЛОК ПАГИНАЦИИ? */ ?>
1
Комментарии

если вы ищете информацию об Ajax, посетите здесь http://wordpress.stackexchange.com/questions/113379/how-to-display-pagination-links-for-wp-user-query-in-ajax

Sabir Abdul Gafoor Shaikh Sabir Abdul Gafoor Shaikh
8 сент. 2013 г. 11:27:03
Все ответы на вопрос 3
9
18

Это должно приблизить вас к решению. Я не тестировал код, но он практически идентичен настройке, которую использовал несколько раз.

/*
 * Начинаем с запроса для получения всех пользователей
 * Нам нужно общее количество пользователей, чтобы рассчитать количество страниц
 */

$count_args  = array(
    'role'      => 'Подписчик',
    'fields'    => 'all_with_meta',
    'number'    => 999999      
);
$user_count_query = new WP_User_Query($count_args);
$user_count = $user_count_query->get_results();

// подсчитываем количество пользователей, найденных в запросе
$total_users = $user_count ? count($user_count) : 1;

// получаем номер текущей страницы и устанавливаем 1, если номер страницы не задан
$page = isset($_GET['p']) ? $_GET['p'] : 1;

// количество пользователей на странице
$users_per_page = 5;

// вычисляем общее количество страниц
$total_pages = 1;
$offset = $users_per_page * ($page - 1);
$total_pages = ceil($total_users / $users_per_page);


// основной запрос пользователей
$args  = array(
    // ищем только роль Подписчика
    'role'      => 'Подписчик',
    // сортируем результаты по display_name
    'orderby'   => 'display_name',
    // возвращаем все поля
    'fields'    => 'all_with_meta',
    'number'    => $users_per_page,
    'offset'    => $offset // пропускаем количество пользователей на странице  
);

// Создаем объект WP_User_Query
$wp_user_query = new WP_User_Query($args);

// Получаем результаты
$authors = $wp_user_query->get_results();

// проверяем, есть ли пользователи
if (!empty($authors))
{
    echo '<div class="author-entry">';
    // перебираем каждого автора
    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>Имя</strong> : <?php echo $author_info->first_name; ?></span><br />
        <span class="ln"><strong>Фамилия</strong> : <?php echo $author_info->last_name; ?></span><br />
        <span class="em"><strong>Email</strong> : <a href="mailto:<?php echo $author_info->user_email; ?>"><?php echo $author_info->user_email; ?></a></span><br />
        <span class="we"><strong>Сайт</strong> : <a href="<?php echo $author_info->user_url; ?>"><?php echo $author_info->user_url; ?></a></span><br />

        <span class="de"><strong>Биография</strong> :<br /><?php echo $author_info->description ; ?></span>
        <div class="clear">&nbsp;</div>

    <?php 
    }
    echo '</div>';
} else {
    echo 'Авторы не найдены';
}

// получаем текущие параметры запроса
$query_string = $_SERVER['QUERY_STRING'];

// Переменная $base хранит полный URL нашей страницы, включая текущий аргумент страницы

// если в админке, базовый URL должен быть админ URL + ваша страница
$base = admin_url('your-page-path') . '?' . remove_query_arg('p', $query_string) . '%_%';

// если на фронтенде, базовый URL - текущая страница
//$base = get_permalink( get_the_ID() ) . '?' . remove_query_arg('p', $query_string) . '%_%';

echo paginate_links( array(
    'base' => $base, // базовый URL, включая аргумент запроса
    'format' => '&p=%#%', // определяет параметр запроса, который будет использоваться (в данном случае "p")
    'prev_text' => __('&laquo; Назад'), // текст для предыдущей страницы
    'next_text' => __('Вперед &raquo;'), // текст для следующей страницы
    'total' => $total_pages, // общее количество страниц
    'current' => $page, // текущая страница
    'end_size' => 1,
    'mid_size' => 5,
));
4 июл. 2012 г. 18:03:14
Комментарии

+1 Было бы здорово, если бы код был разбит и объяснен :)

kaiser kaiser
4 июл. 2012 г. 23:28:04

Добавил более понятные комментарии и исправил пару багов :)

Pippin Pippin
4 июл. 2012 г. 23:53:22

Спасибо за это @Pippin, я попробую, когда доберусь до студии. Один вопрос: что мне вставлять в часть 'your-page-path' в admin_url? Это корень моего сайта?

Osu Osu
5 июл. 2012 г. 19:02:10

Страница, которая показывает ваших пользователей, находится в админке или на фронтенде?

Pippin Pippin
5 июл. 2012 г. 23:10:23

Привет @Pippin, это на фронтенде, но мне было интересно, для чего нужна эта часть кода :)

Osu Osu
6 июл. 2012 г. 12:41:58

Эта часть кода необходима для генерации ссылок пагинации. Функция paginate_links() должна знать, к какому URL добавлять параметры запроса. Я просто привел вам пример для админки и для фронтенда, но версию для админки можно игнорировать.

Pippin Pippin
6 июл. 2012 г. 16:57:43

Мне очень нравится этот шаблон. Полностью рабочий вариант ;) большое спасибо. Для тех, кто копирует и вставляет (и, возможно, редактирует) — переменную $limit нужно заменить на $users_per_page. Похоже, это упустили, когда добавляли пояснения.

Sagive Sagive
11 сент. 2014 г. 15:38:49

Интересный подход. Я заметил, что вы выполняете здесь 2 запроса: первый — чтобы получить всех пользователей, а второй — только пользователей на нужной странице. Не будет ли производительнее использовать всего 1 запрос, а затем разбивать результаты на страницы с помощью array_slice? Кажется, что раз вы работаете с одними и теми же данными в двух разных запросах, можно сэкономить ресурсы, убрав один из них.

codescribblr codescribblr
22 июн. 2015 г. 05:35:06

Запрос для подсчёта общего количества пользователей можно заменить на $total_users = $wp_user_query->get_total();

1naveengiri 1naveengiri
15 мар. 2019 г. 14:18:12
Показать остальные 4 комментариев
6
12

Вам действительно не стоит использовать ответ от Pippin. Этот запрос очень неэффективен. В примере $user_count_query может вернуть до 999,999 пользователей из вашей базы данных в скрипт, со всеми полями пользователей. Это почти наверняка приведёт к превышению лимитов памяти и/или времени выполнения PHP, если/когда ваш сайт вырастет достаточно большим.

Но в 2012 году это могло быть единственным решением.

Вот более правильный способ. В этом примере у меня есть только следующая и предыдущая страницы, но если вам нужна нумерованная пагинация, переменные для её реализации уже есть. Насколько мне известно, в WordPress нет встроенной функции пагинации, совместимой с WP_User_Query.

<?php

// Переменные пагинации
$current_page = get_query_var('paged') ? (int) get_query_var('paged') : 1;
$users_per_page = 2; // УВЕЛИЧЬТЕ ЭТО ЗНАЧЕНИЕ ПОСЛЕ ТЕСТИРОВАНИЯ ;)

$args = array(
    'number' => $users_per_page, // Сколько пользователей на странице
    'paged' => $current_page // Какую страницу получить, начиная с 1.
);

$users = new WP_User_Query( $args );

$total_users = $users->get_total(); // Общее количество пользователей (вне текущей страницы)
$num_pages = ceil($total_users / $users_per_page); // Сколько всего страниц с пользователями потребуется

?>
    <h3>Страница <?php echo $current_page; ?> из <?php echo $num_pages; ?></h3>
    <p>Отображается <?php echo $users_per_page; ?> из <?php echo $total_users; ?> пользователей</p>

    <table>
        <thead>
            <tr>
                <th>Имя</th>
                <th>Фамилия</th>
                <th>Email</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
        // Предыдущая страница
        if ( $current_page > 1 ) {
            echo '<a href="'. add_query_arg(array('paged' => $current_page-1)) .'">Предыдущая страница</a>';
        }

        // Следующая страница
        if ( $current_page < $num_pages ) {
            echo '<a href="'. add_query_arg(array('paged' => $current_page+1)) .'">Следующая страница</a>';
        }
        ?>
    </p>

Пример, показывающий страницу 2:

таблица пользователей, начиная со страницы 2


Обновление 8.06.2018: Как добавить номера страниц вместо "Следующая/Предыдущая"

Если вы хотите иметь нумерацию страниц вместо ссылок "Следующая/Предыдущая", вот как это можно реализовать. Обратите внимание, что вам нужно будет заменить номера на ссылки страниц, в этом примере они не кликабельны (основано на https://stackoverflow.com/a/11274294/470480, модифицировано для отображения постоянного количества средних номеров и без добавления "..." если страницы не пропущены).

Вы также можете посмотреть мой gist-файл, который содержит переиспользуемую функцию для этой цели.

$current_page = 5; // Пример
$num_pages = 10; // Пример

$edge_number_count = 2; // Можно изменить, необязательно

$start_number = $current_page - $edge_number_count;
$end_number = $current_page + $edge_number_count;

// Минус один, чтобы не разделять начальный номер без необходимости, например: "1 ... 2 3" должно начинаться как "1 2 3"
if ( ($start_number - 1) < 1 ) {
    $start_number = 1;
    $end_number = min($num_pages, $start_number + ($edge_number_count*2));
}

// Плюс один, чтобы не разделять конечный номер без необходимости, например: "8 9 ... 10" должно оставаться "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} ";

Вывод (со страницы 1 по 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]
14 мая 2017 г. 05:10:44
Комментарии

Согласен. Ответ Pippin требует 2 запроса к базе данных, чего по возможности следует избегать.

The Sumo The Sumo
18 авг. 2017 г. 18:16:27

Привет @radley-sustaire, это отличное решение, но мне интересно, есть ли способ изменить часть "displaying 2 of 6 users" на фактический диапазон пользователей на странице. Например, "displaying 1-2 of 6" для страницы 1, "3-4 of 6" для страницы 2 и "5-6 of 6" для страницы 3. Сейчас везде отображается просто "2 of 6".

damienoneill2001 damienoneill2001
13 февр. 2018 г. 12:50:27

@damienoneill2001 Хорошая идея, можно начать с чего-то вроде: $start_user_num = (($current_page-1) * $users_per_page) + 1; и $end_user_num = $start_user_num + count($users->get_results());.

Radley Sustaire Radley Sustaire
14 февр. 2018 г. 01:04:27

@RadleySustaire отлично, спасибо за это. Сначала я получил следующую ошибку: Call to a member function get_results() on a non-object, поэтому я изменил $end_user_number на $start_user_num + ($users_per_page-1);, и это решило проблему. Ещё раз спасибо!

damienoneill2001 damienoneill2001
14 февр. 2018 г. 13:42:49

Оказалось, я поторопился с этим выводом. Когда я перехожу на последнюю страницу, которая не содержит полного списка пользователей, очевидно, отображается неправильное значение для $end_user_number в моём решении. Придётся вернуться к чертёжной доске, ха!

damienoneill2001 damienoneill2001
14 февр. 2018 г. 15:41:20

paged в моём случае не работает, вместо этого работает offset

Tim Hallman Tim Hallman
6 мар. 2019 г. 22:23:58
Показать остальные 1 комментариев
0

Полная заслуга принадлежит @radley-sustaire за его ответ, но я заметил небольшую ошибку в нем, поэтому делюсь своей версией ответа здесь.

В моей версии я также фильтровал результаты по местоположению, ключевым словам и т.д., поэтому на некоторых страницах было меньше результатов, чем указано в переменной '$users_per_page'. Например, если у меня было установлено отображать 10 пользователей на странице, но результаты фильтра возвращали только 3 пользователя, вверху страницы появлялось сообщение "Displaying 10 of 3 users". Очевидно, это не имело смысла, поэтому я добавил простое условие "if" для проверки, является ли количество результатов больше переменной '$users_per_page'.

Radley, если ты отредактируешь свой ответ с этим обновлением, я с радостью проголосую за него как за правильный ответ, так как считаю его лучше решения Pippin.

Вот окончательный код для тех, кому он нужен.

<?php

// Переменные пагинации
$current_page = get_query_var('paged') ? (int) get_query_var('paged') : 1;
$users_per_page = 10;

$args = array(
    'number' => $users_per_page, // Сколько показывать на странице
    'paged' => $current_page // Какую страницу получать, начиная с 1.
);

$users = new WP_User_Query( $args );

$total_users = $users->get_total(); // Общее количество пользователей (за пределами текущей страницы)
$num_pages = ceil($total_users / $users_per_page); // Сколько страниц с пользователями нам понадобится

if ($total_users < $users_per_page) {$users_per_page = $total_users;}

?>
    <h3>Страница <?php echo $current_page; ?> из <?php echo $num_pages; ?></h3>
    <p>Показано <?php echo $users_per_page; ?> из <?php echo $total_users; ?> пользователей</p>

    <table>
        <thead>
            <tr>
                <th>Имя</th>
                <th>Фамилия</th>
                <th>Email</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
        // Предыдущая страница
        if ( $current_page > 1 ) {
            echo '<a href="'. add_query_arg(array('paged' => $current_page-1)) .'">Предыдущая страница</a>';
        }

        // Следующая страница
        if ( $current_page < $num_pages ) {
            echo '<a href="'. add_query_arg(array('paged' => $current_page+1)) .'">Следующая страница</a>';
        }
        ?>
    </p>
21 авг. 2017 г. 10:56:06