Как создавать динамические таблицы в WordPress с помощью шорткодов и AJAX

В WordPress часто возникает задача отображать данные в виде таблиц, причем желательно, чтобы эти таблицы были динамическими — например, подгружали данные без перезагрузки страницы, позволяли фильтровать или сортировать информацию. В этой статье мы разберем, как создать динамическую таблицу с применением шорткодов и AJAX-запросов, чтобы пользователи сайта получали актуальные данные на лету.

Почему динамические таблицы важны для WordPress

Таблицы — удобный способ структурировать информацию, будь то списки товаров, расписания, отчеты или аналитика. Статические таблицы — это просто HTML-код, который не меняется без обновления страницы. А динамические позволяют:

  • Обновлять содержимое таблицы без перезагрузки страницы
  • Загружать большие объемы данных по частям (пагинация)
  • Добавлять фильтры и сортировку на стороне сервера
  • Улучшать пользовательский опыт и скорость работы сайта

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

Создаем шорткод для вывода таблицы

Начнем с простого шорткода, который выводит базовую таблицу с данными, полученными из базы данных WordPress. Например, сделаем таблицу, которая выводит последние 10 записей из определенной категории.

function wprobot_dynamic_table_shortcode($atts) {
    global $wpdb;
    $atts = shortcode_atts(array(
        'category' => '',
        'posts_per_page' => 10
    ), $atts, 'wprobot_dynamic_table');

    $category = sanitize_text_field($atts['category']);
    $posts_per_page = intval($atts['posts_per_page']);

    $query = $wpdb->prepare(
        "SELECT p.ID, p.post_title, p.post_date FROM {$wpdb->posts} p
         INNER JOIN {$wpdb->term_relationships} tr ON (p.ID = tr.object_id)
         INNER JOIN {$wpdb->term_taxonomy} tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)
         INNER JOIN {$wpdb->terms} t ON (tt.term_id = t.term_id)
         WHERE p.post_type = 'post' AND p.post_status = 'publish' AND t.slug = %s
         ORDER BY p.post_date DESC LIMIT %d",
        $category, $posts_per_page
    );

    $results = $wpdb->get_results($query);

    if (empty($results)) {
        return '<p>Нет записей для отображения.</p>';
    }

    $output = '<table class="wprobot-table"><thead><tr><th>Заголовок</th><th>Дата публикации</th></tr></thead><tbody>';
    foreach ($results as $row) {
        $url = get_permalink($row->ID);
        $output .= '<tr><td><a href="'. esc_url($url) .'">'. esc_html($row->post_title) .'</a></td><td>'. esc_html(date('d.m.Y', strtotime($row->post_date))) .'</td></tr>';
    }
    $output .= '</tbody></table>';

    return $output;
}
add_shortcode('wprobot_dynamic_table', 'wprobot_dynamic_table_shortcode');

Этот код создает шорткод [wprobot_dynamic_table category="novosti" posts_per_page="10"], который выводит таблицу с последними 10 постами из категории «novosti».

Добавляем AJAX для динамической подгрузки данных

Чтобы таблица была по-настоящему динамической, сделаем подгрузку данных по AJAX, например, добавим пагинацию без перезагрузки страницы. В этом примере мы сделаем кнопку «Загрузить еще», которая будет подгружать следующие записи.

Шаг 1. Добавляем скрипт и локализацию

function wprobot_enqueue_scripts() {
    wp_enqueue_script('wprobot-ajax-table', get_stylesheet_directory_uri() . '/js/wprobot-ajax-table.js', array('jquery'), '1.0', true);
    wp_localize_script('wprobot-ajax-table', 'wprobot_ajax_obj', array(
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('wprobot_ajax_nonce')
    ));
}
add_action('wp_enqueue_scripts', 'wprobot_enqueue_scripts');

Этот код подключает JS-файл и передает в него URL для AJAX-запросов и nonce для безопасности.

Шаг 2. Обрабатываем AJAX-запросы в PHP

function wprobot_load_more_posts() {
    check_ajax_referer('wprobot_ajax_nonce', 'security');

    $paged = isset($_POST['paged']) ? intval($_POST['paged']) : 1;
    $category = isset($_POST['category']) ? sanitize_text_field($_POST['category']) : '';
    $posts_per_page = 10;

    if ($paged < 1) $paged = 1;

    $offset = ($paged - 1) * $posts_per_page;

    global $wpdb;
    $query = $wpdb->prepare(
        "SELECT p.ID, p.post_title, p.post_date FROM {$wpdb->posts} p
         INNER JOIN {$wpdb->term_relationships} tr ON (p.ID = tr.object_id)
         INNER JOIN {$wpdb->term_taxonomy} tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)
         INNER JOIN {$wpdb->terms} t ON (tt.term_id = t.term_id)
         WHERE p.post_type = 'post' AND p.post_status = 'publish' AND t.slug = %s
         ORDER BY p.post_date DESC LIMIT %d, %d",
        $category, $offset, $posts_per_page
    );

    $results = $wpdb->get_results($query);

    if (empty($results)) {
        wp_send_json_error('Нет больше записей');
    }

    $output = '';
    foreach ($results as $row) {
        $url = get_permalink($row->ID);
        $output .= '<tr><td><a href="'. esc_url($url) .'">'. esc_html($row->post_title) .'</a></td><td>'. esc_html(date('d.m.Y', strtotime($row->post_date))) .'</td></tr>';
    }

    wp_send_json_success($output);
}
add_action('wp_ajax_wprobot_load_more', 'wprobot_load_more_posts');
add_action('wp_ajax_nopriv_wprobot_load_more', 'wprobot_load_more_posts');

Шаг 3. Создаем JavaScript для обработки клика

Файл js/wprobot-ajax-table.js:

jQuery(document).ready(function($) {
    var paged = 2;
    var category = $('.wprobot-table').data('category');

    $('#wprobot-load-more').on('click', function(e) {
        e.preventDefault();
        var button = $(this);
        button.prop('disabled', true).text('Загрузка...');

        $.ajax({
            url: wprobot_ajax_obj.ajax_url,
            type: 'POST',
            data: {
                action: 'wprobot_load_more',
                paged: paged,
                category: category,
                security: wprobot_ajax_obj.nonce
            },
            success: function(response) {
                if (response.success) {
                    $('.wprobot-table tbody').append(response.data);
                    paged++;
                    button.prop('disabled', false).text('Загрузить еще');
                } else {
                    button.text('Больше записей нет');
                    button.prop('disabled', true);
                }
            },
            error: function() {
                button.prop('disabled', false).text('Ошибка загрузки');
            }
        });
    });
});

Подключаем пагинацию и выводим кнопку

Обновим шорткод, чтобы таблица содержала data-атрибут с категорией и кнопку для загрузки данных:

function wprobot_dynamic_table_shortcode($atts) {
    global $wpdb;
    $atts = shortcode_atts(array(
        'category' => '',
        'posts_per_page' => 10
    ), $atts, 'wprobot_dynamic_table');

    $category = sanitize_text_field($atts['category']);
    $posts_per_page = intval($atts['posts_per_page']);

    $query = $wpdb->prepare(
        "SELECT p.ID, p.post_title, p.post_date FROM {$wpdb->posts} p
         INNER JOIN {$wpdb->term_relationships} tr ON (p.ID = tr.object_id)
         INNER JOIN {$wpdb->term_taxonomy} tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)
         INNER JOIN {$wpdb->terms} t ON (tt.term_id = t.term_id)
         WHERE p.post_type = 'post' AND p.post_status = 'publish' AND t.slug = %s
         ORDER BY p.post_date DESC LIMIT %d",
        $category, $posts_per_page
    );

    $results = $wpdb->get_results($query);

    if (empty($results)) {
        return '<p>Нет записей для отображения.</p>';
    }

    $output = '<table class="wprobot-table" data-category="'. esc_attr($category) .'"><thead><tr><th>Заголовок</th><th>Дата публикации</th></tr></thead><tbody>';
    foreach ($results as $row) {
        $url = get_permalink($row->ID);
        $output .= '<tr><td><a href="'. esc_url($url) .'">'. esc_html($row->post_title) .'</a></td><td>'. esc_html(date('d.m.Y', strtotime($row->post_date))) .'</td></tr>';
    }
    $output .= '</tbody></table>';
    $output .= '<button id="wprobot-load-more" type="button">Загрузить еще</button>';

    return $output;
}
add_shortcode('wprobot_dynamic_table', 'wprobot_dynamic_table_shortcode');

Советы по оптимизации и безопасности

При работе с AJAX и базой данных важно соблюдать несколько правил:

  • Используйте wp_nonce для защиты AJAX-запросов от CSRF-атак.
  • Обязательно фильтруйте и экранируйте все входящие данные с помощью функций sanitize_text_field, intval, esc_html, esc_url.
  • Для сложных и больших таблиц рассмотрите использование специализированных плагинов, например, ABC Pagination для удобной навигации по страницам.
  • Кешируйте результаты запросов там, где это возможно, чтобы снизить нагрузку на сервер.

Примеры полезных плагинов для работы с таблицами в WordPress

Если не хочется писать код с нуля, можно использовать плагины, которые позволяют создавать и управлять таблицами с динамическими функциями:

  • TablePress — один из самых популярных плагинов для создания таблиц. Позволяет импортировать данные, добавлять сортировку и фильтры.
  • WPDataTables — мощный инструмент для работы с большими наборами данных, поддерживает AJAX-подгрузку и интеграцию с внешними источниками.
  • ABC Pagination — улучшает отображение списков и таблиц с постраничной навигацией, полезен для динамических таблиц с большим количеством записей. Подробнее на wpshop.ru.

Заключение: динамические таблицы — шаг к удобству пользователей

Создание динамических таблиц с помощью шорткодов и AJAX — отличный способ сделать сайт на WordPress более интерактивным и удобным для посетителей. Вы можете самостоятельно расширять функционал, добавлять фильтры, сортировку, пагинацию и многое другое. Приведенные примеры — базовый фундамент, который легко адаптируется под любые задачи.

Как настроить автоматическое отображение связанных записей в WordPress
16.12.2025
Как автоматически отключить и включить плагин в WordPress с помощью кода
27.03.2026
Как автоматически отправлять сообщения в Discord из WordPress
16.04.2026
Как автоматически сохранять данные пользователя в WordPress без плагинов
14.03.2026
Как автоматически создавать выделенные посты в WordPress с помощью категорий
11.03.2026