Пагинация в административной панели WordPress — важный элемент для удобного управления большим количеством записей. Стандартный список постов в разделе «Записи» или «Страницы» уже оснащён пагинацией, но что делать, если вы создаёте кастомный тип записей (Custom Post Type, CPT) и хотите контролировать пагинацию в собственном списке, например, во вложенной странице меню или кастомном админ-экранe?
Почему нужна кастомная пагинация в админке WordPress
Стандартные механизмы пагинации в WP Admin работают для штатных списков записей, но при разработке плагинов или тем часто требуется выводить списки CPT в собственных админ-страницах. В таких случаях нужно реализовать пагинацию вручную или с помощью специальных функций, чтобы не перегружать интерфейс и не создавать слишком длинные списки.
Кроме того, правильная пагинация улучшает производительность загрузки страницы, так как запросы к базе данных ограничиваются определённым количеством записей, а также упрощает навигацию для пользователя.
Рассмотрим, как добавить пагинацию в WP Admin для кастомного списка записей с помощью WP_List_Table — базового класса WordPress, который используется для вывода таблиц в админке.
Использование класса WP_List_Table для пагинации кастомных записей
Класс WP_List_Table не документирован официально, но широко применяется разработчиками. Чтобы создать собственный список с пагинацией, нужно наследовать этот класс и реализовать несколько обязательных методов.
Основная идея — в методе prepare_items() выполнить запрос к базе с параметрами пагинации, а затем передать полученные данные в таблицу.
Основные шаги:
- Создать класс, унаследованный от
WP_List_Table. - Определить колонки таблицы в методе
get_columns(). - Реализовать метод
prepare_items(), где выполнить запрос с LIMIT и OFFSET, учитывая текущую страницу. - Добавить пагинацию через метод
set_pagination_args().
Пример реализации пагинации для CPT «product»
if (!class_exists('WP_List_Table')) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
class Wppagenavi_Product_List extends WP_List_Table {
private $example_data = [];
public function __construct() {
parent::__construct([
'singular' => 'product',
'plural' => 'products',
'ajax' => false
]);
}
public function get_columns() {
return [
'cb' => '<input type="checkbox" />',
'ID' => 'ID',
'title' => 'Название товара',
'date' => 'Дата'
];
}
public function column_cb($item) {
return sprintf('<input type="checkbox" name="product[]" value="%d" />', $item->ID);
}
public function column_title($item) {
$edit_link = get_edit_post_link($item->ID);
return sprintf('<a href="%s">%s</a>', $edit_link, esc_html($item->post_title));
}
public function prepare_items() {
global $wpdb;
$per_page = 10; // Количество записей на странице
$current_page = $this->get_pagenum();
$offset = ($current_page - 1) * $per_page;
// Получаем общее количество записей CPT 'product'
$total_items = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = 'product' AND post_status = 'publish'");
// Получаем записи для текущей страницы
$query = $wpdb->prepare(
"SELECT ID, post_title, post_date FROM {$wpdb->posts} WHERE post_type = %s AND post_status = 'publish' ORDER BY post_date DESC LIMIT %d OFFSET %d",
'product', $per_page, $offset
);
$this->example_data = $wpdb->get_results($query);
$columns = $this->get_columns();
$hidden = [];
$sortable = [];
$this->_column_headers = [$columns, $hidden, $sortable];
$this->items = $this->example_data;
$this->set_pagination_args([
'total_items' => $total_items,
'per_page' => $per_page,
'total_pages' => ceil($total_items / $per_page)
]);
}
// Выводим колонки 'ID' и 'date'
public function column_ID($item) {
return $item->ID;
}
public function column_date($item) {
return date('Y-m-d', strtotime($item->post_date));
}
}
// Функция для отображения списка в админке
function wppagenavi_render_product_list_page() {
$productListTable = new Wppagenavi_Product_List();
$productListTable->prepare_items();
echo '<div class="wrap"><h1>Список товаров</h1>';
echo '<form method="post">';
$productListTable->display();
echo '</form></div>';
}
// Регистрируем страницу меню в админке
add_action('admin_menu', function() {
add_menu_page('Товары', 'Товары', 'manage_options', 'wppagenavi-products', 'wppagenavi_render_product_list_page');
});
В данном примере мы создаём кастомный список товаров с пагинацией по 10 записей на страницу. Используем прямые SQL-запросы через $wpdb, чтобы получить количество и сами записи с учётом текущей страницы. Метод set_pagination_args() отвечает за отображение навигации по страницам внизу таблицы.
Расширение функционала: сортировка и фильтрация
Для удобства пользователей можно добавить сортировку по колонкам и фильтры по статусу или меткам. Для этого в классе нужно реализовать методы get_sortable_columns() и обработать параметры сортировки в запросе.
Например, чтобы добавить сортировку по дате:
public function get_sortable_columns() {
return [
'date' => ['post_date', true],
'title' => ['post_title', false]
];
}
// В prepare_items обработать сортировку:
$order_by = (!empty($_GET['orderby'])) ? esc_sql($_GET['orderby']) : 'post_date';
$order = (!empty($_GET['order'])) ? esc_sql($_GET['order']) : 'DESC';
$query = $wpdb->prepare(
"SELECT ID, post_title, post_date FROM {$wpdb->posts} WHERE post_type = %s AND post_status = 'publish' ORDER BY $order_by $order LIMIT %d OFFSET %d",
'product', $per_page, $offset
);
Такой подход позволит пользователю кликать по заголовкам колонок для сортировки.
Плагины для расширения функционала и альтернативные решения
Если не хочется писать собственный класс, можно использовать готовые плагины, которые добавляют расширенные списки с пагинацией для CPT:
- Clearfy Pro — содержит расширенные админ-инструменты, включая улучшенную навигацию и фильтрацию.
- Expert Review — позволяет создавать удобные списки с кастомными настройками отображения.
Однако собственная реализация на базе WP_List_Table даёт максимум контроля и минимизирует нагрузку на систему.
Оптимизация запросов и кеширование пагинации в админке
При большом количестве записей стоит задуматься об оптимизации запросов. Используйте индексы в базе и минимизируйте количество выборок. Также можно применять транзиенты (transients) для кеширования результатов, чтобы не выполнять запросы при каждом обновлении страницы.
Пример простого кеширования в prepare_items():
$cache_key = 'wppagenavi_products_page_' . $current_page;
$cached_data = get_transient($cache_key);
if ($cached_data !== false) {
$this->example_data = $cached_data['items'];
$total_items = $cached_data['total'];
} else {
$total_items = $wpdb->get_var(...);
$this->example_data = $wpdb->get_results(...);
set_transient($cache_key, [
'items' => $this->example_data,
'total' => $total_items
], 3600); // кеш на час
}
Это значительно снизит нагрузку при частом обращении к списку.
Вывод
Добавление пагинации в WP Admin для кастомных типов записей — задача, которая требует понимания работы WP_List_Table и правильной организации запросов к базе. Собственная реализация позволяет гибко настраивать отображение, сортировку и фильтры, а также оптимизировать производительность. В сочетании с кешированием и проверенными плагинами (например, Clearfy Pro) вы получите удобный и быстрый админ-интерфейс для управления большим количеством записей.