Как добавить WP_List_Table на страницу WordPress?

17 дек. 2015 г., 22:30:59
Просмотры: 18.3K
Голосов: 8

У меня есть WP_List_Table, и я хочу добавить её на страницу, но в поисках не нашёл примеров, как это сделать. У кого-нибудь есть готовый пример кода для реализации этой задачи?

<?php
/*
Plugin Name: Add Parl Plugin 2
Description: Плагин для добавления парламентов
Plugin URI: "http://www.ttparliaments.org"
Author URI: ""
Author: Napoleon Okunna
License: ""
Version: 1.0
*/

global $custom_table_example_db_version;
$custom_table_example_db_version = '1.1'; // версия изменена с 1.0 на 1.1
global $wpdb;
global $custom_table_example_db_version;

$table_name = $wpdb->prefix . 'oop_parliamentary_info'; // не забываем про префикс таблиц


/**
 * ЧАСТЬ 2. Определение кастомного списка таблиц
 * ============================================================================
 *
 * В этой части мы определяем класс кастомной таблицы,
 * который будет отображать записи из БД в виде удобной таблицы
 *
 * http://codex.wordpress.org/Class_Reference/WP_List_Table
 * http://wordpress.org/extend/plugins/custom-list-table-example/
 */

if (!class_exists('WP_List_Table')) {
    require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
}

/**
 * Класс Custom_Table_Example_List_Table для отображения
 * записей нашей кастомной таблицы
 */
class Custom_Table_Example_List_Table extends WP_List_Table
{
    /**
     * [ОБЯЗАТЕЛЬНО] Объявляем конструктор и задаём базовые параметры
     */
    function __construct()
    {
        global $status, $page;

        parent::__construct(array(
            'singular' => 'person',
            'plural' => 'persons',
        ));
    }

    /**
     * [ОБЯЗАТЕЛЬНО] Стандартный рендерер колонок
     *
     * @param $item - строка (массив ключ-значение)
     * @param $column_name - строка (ключ)
     * @return HTML
     */
    function column_default($item, $column_name)
    {
        return $item[$column_name];
    }

    /**
     * [ОПЦИОНАЛЬНО] Пример рендеринга конкретной колонки
     *
     * имя метода должно быть вида: "column_[имя_колонки]"
     *
     * @param $item - строка (массив ключ-значение)
     * @return HTML
     */
    function column_age($item)
    {
        return '<em>' . $item['age'] . '</em>';
    }

    /**
     * [ОПЦИОНАЛЬНО] Пример рендеринга колонки с действиями
     * при наведении показываются ссылки "Редактировать | Удалить"
     *
     * @param $item - строка (массив ключ-значение)
     * @return HTML
     */
    function column_name($item)
    {
        $actions = array(
            'edit'      => sprintf('<a href="?page=%s&action=%s&book=%s">Редактировать</a>',$_REQUEST['page'],'edit',$item['ParliamentaryID']),
            'delete'    => sprintf('<a href="?page=%s&action=%s&book=%s">Удалить</a>',$_REQUEST['page'],'delete',$item['ParliamentaryID']),
        );

        return sprintf('%1$s %2$s', $item['booktitle'], $this->row_actions($actions) );
    }

    /**
     * [ОБЯЗАТЕЛЬНО] Рендеринг колонки с чекбоксами
     *
     * @param $item - строка (массив ключ-значение)
     * @return HTML
     */
    function column_cb($item)
    {
        return sprintf(
            '<input type="checkbox" name="id[]" value="%s" />',
            $item['id']
        );
    }

    /**
     * [ОБЯЗАТЕЛЬНО] Метод возвращает колонки для отображения в таблице
     * можно пропустить колонки, которые не нужно показывать
     * например, содержание или описание
     *
     * @return array
     */
    function get_columns()
    {
        $columns = array(
            'cb' => '<input type="checkbox" />', // Рендерим чекбокс вместо текста
            'Title' => __('Title', 'custom_table_example'),
            'StartDate' => __('StartDate', 'custom_table_example'),
            'EndDate' => __('EndDate', 'custom_table_example'),
            'IsCurrent' => __('IsCurrent', 'custom_table_example'),
            ParliamentaryID =>'<a href=#>Редактировать</a>',
        );
        return $columns;
    }

    /**
     * [ОПЦИОНАЛЬНО] Метод возвращает колонки, по которым можно сортировать таблицу
     * все строки в массиве - имена колонок
     * true у колонки name означает, что сортировка по ней включена по умолчанию
     *
     * @return array
     */
    function get_sortable_columns()
    {
        $sortable_columns = array(
            'Title' => array('Title', true),
            'StartDate' => array('StartDate', false),
            'EndDate' => array('EndDate', false),
            'IsCurrent' => __('IsCurrent', false),
            'ParliamentaryID'=> __('ParliamentaryID', false),
        );
        return $sortable_columns;
    }

    /**
     * [ОПЦИОНАЛЬНО] Возвращает массив групповых действий, если они есть
     *
     * @return array
     */
    function get_bulk_actions()
    {
        $actions = array(
            'delete' => 'Удалить',
            'edit' =>'Редактировать'
        );
        return $actions;
    }

    /**
     * [ОПЦИОНАЛЬНО] Метод обрабатывает групповые действия
     * может быть вне класса
     * нельзя использовать wp_redirect, так как вывод уже начат
     * в этом примере мы обрабатываем действие удаления
     * сообщение об успешном удалении будет показано на странице в следующей части
     */
    function process_bulk_action()
    {
        global $wpdb;
        $table_name = $wpdb->prefix . 'cte'; // не забываем про префикс таблиц

        if ('delete' === $this->current_action()) {
            $ids = isset($_REQUEST['id']) ? $_REQUEST['id'] : array();
            if (is_array($ids)) $ids = implode(',', $ids);

            if (!empty($ids)) {
                $wpdb->query("DELETE FROM $table_name WHERE id IN($ids)");
            }
        }
        if ('Edit' === $this->current_action()) {
            echo('Редактировать');
        }
    }

    /**
     * [ОБЯЗАТЕЛЬНО] Самый важный метод
     *
     * Получает строки из БД и подготавливает их для отображения в таблице
     */
    function prepare_items()
    {
        global $wpdb;
        $table_name = $wpdb->prefix . 'cte'; // не забываем про префикс таблиц
        $table_name='oop_parliamentary_info';

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

        $columns = $this->get_columns();
        $hidden = array();
        $sortable = $this->get_sortable_columns();

        // конфигурируем заголовки таблицы, определённые в наших методах
        $this->_column_headers = array($columns, $hidden, $sortable);

        // [ОПЦИОНАЛЬНО] обрабатываем групповые действия, если они есть
        $this->process_bulk_action();

        // используется для настроек пагинации
        $total_items = $wpdb->get_var("SELECT COUNT(ParliamentaryID) FROM $table_name");

        // подготавливаем параметры запроса: текущая страница, сортировка и направление
        $paged = isset($_REQUEST['paged']) ? max(0, intval($_REQUEST['paged']) - 1) : 0;

        $orderby = (isset($_REQUEST['orderby']) && in_array($_REQUEST['orderby'], array_keys($this->get_sortable_columns()))) ? $_REQUEST['orderby'] : 'name';
        $order = (isset($_REQUEST['order']) && in_array($_REQUEST['order'], array('asc', 'desc'))) ? $_REQUEST['order'] : 'asc';

        // [ОБЯЗАТЕЛЬНО] определяем массив $items
        // последний аргумент ARRAY_A означает, что мы получаем массив
        $this->items = $wpdb->get_results($wpdb->prepare("SELECT Title,StartDate,EndDate,ParliamentaryID  FROM oop_parliamentary_info  ", $per_page, $paged), ARRAY_A);
       
        // перебираем элементы и форматируем строки
        foreach ($this->items as $item ) {
            static $row_class = '';
            $row_class = ( $row_class == '' ? ' class="alternate"' : '' );

            echo '<tr' . $row_class . '>';
            echo '</tr>';
        }

        // [ОБЯЗАТЕЛЬНО] настраиваем пагинацию
        $this->set_pagination_args(array(
            'total_items' => $total_items, // общее количество элементов
            'per_page' => $per_page, // количество элементов на странице
            'total_pages' => ceil($total_items / $per_page) // вычисляем количество страниц
        ));
    }

    function single_row_columns($item) {
        list($columns, $hidden) = $this->get_column_info();
        foreach ($columns as $column_name => $column_display_name) {
            $class = "class='$column_name column-$column_name'";

            $style = '';
            if (in_array($column_name, $hidden))
                $style = ' style="display:none;"';

            $attributes = "$class$style";

            if ('cb' == $column_name) {
                echo  "<td $attributes>";
                echo "</td>";
            }
            elseif ('ParliamentaryID' == $column_name) {
                echo "<td $attributes>";
                echo '<a href="#">', '';
                echo "</a>";

                echo "<div class='row-actions'><span class='edit'>";
                echo sprintf('<a class="editParlRow"  href="?page=%s&action=%s&gid=%s">Редактировать</a>',$_REQUEST['page'],'edit',$item['ParliamentaryID']);
                echo "</span> | <span class='trash'>";
                echo sprintf('<a href="?page=%s&action=%s&gid=%s">Удалить</a>',$_REQUEST['page'],'delete',$item['ParliamentaryID']);
                echo "</span></div></td>";
            }
            else {
                echo "<td $attributes>";
                echo $this->column_default( $item, $column_name );
                echo "</td>";
            }
        }
    }
}
5
Комментарии

На какую страницу вы добавляете это? В админ-разделе сайта или на кастомной странице? Вы хотите иметь возможность фильтровать результаты или просто выводить контент списком? Можете также показать, откуда вы берете данные для заполнения таблиц?

jgraup jgraup
17 дек. 2015 г. 22:42:55

У меня получилось сделать это на странице админки, но я хочу, чтобы это работало на кастомной странице или вообще на любой странице

Napstar Napstar
17 дек. 2015 г. 22:47:46

Это выглядит как внутренняя функциональность - "Хотя WP_List_Table был разработан для внутреннего использования и не учитывал многие аспекты для кастомных подклассов, мы признаем, что разработчики используют их, и что доработка принесет пользу как реализациям, так и будущему сопровождению." - https://make.wordpress.org/core/2015/08/08/list-table-changes-in-4-3/ Вы просто пытаетесь вывести данные столбцов на фронтенде?

jgraup jgraup
17 дек. 2015 г. 22:52:38

Существует довольно много jQuery плагинов для работы с таблицами, например http://www.unheap.com/section/user-interface/filter-sort/ и http://www.unheap.com/section/media/tables-graphs/

jgraup jgraup
17 дек. 2015 г. 23:00:25

@jgraup да, я пытаюсь вывести данные столбцов на фронтенде

Napstar Napstar
17 дек. 2015 г. 23:10:18
Все ответы на вопрос 1
3
11

Ваша WP_List_Table будет отличаться — этот код адаптирован из WP_List_Table – пошаговое руководство и использует GIST: Пример плагина для использования класса WP_List_Table (полная версия). Вам нужно будет адаптировать свои методы, чтобы включить CSS и на фронтенде (не включено в этот ответ).

ВНИМАНИЕ :

Поскольку этот класс помечен как приватный, разработчики должны использовать его на свой страх и риск, так как этот класс может измениться в будущих версиях WordPress. Разработчикам, использующим этот класс, настоятельно рекомендуется тестировать свои плагины со всеми бета- и RC-версиями WordPress для поддержания совместимости.

ПОДГОТОВКА ФРОНТЕНДА

add_action ('init', function(){

   // Если мы не в админке, мы не ожидаем загрузки этих файлов

   if( ! is_admin() ){

       require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
       require_once( ABSPATH . 'wp-admin/includes/screen.php' );
       require_once( ABSPATH . 'wp-admin/includes/class-wp-screen.php' );
       require_once( ABSPATH . 'wp-admin/includes/template.php' );

       global $myListTable;
       $myListTable = new My_Example_List_Table();
   }
});

ВЫВОД

function my_render_list_page(){

    global $myListTable;

    echo '</pre><div class="wrap"><h2>Мой тест таблицы</h2>';
    $myListTable->prepare_items();

    ?>
    <form method="post">
        <input type="hidden" name="page" value="ttest_list_table">
    <?php

        $myListTable->search_box( 'поиск', 'search_id' );
        $myListTable->display();

    echo '</form></div>';
}

НА ВАШЕЙ СТРАНИЦЕ

my_render_list_page();

СЖАТАЯ ВЕРСИЯ

function my_render_list_page(){

    static $myListTable;
    if( ! isset($myListTable)) {
        require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
        require_once(ABSPATH . 'wp-admin/includes/screen.php');
        require_once(ABSPATH . 'wp-admin/includes/class-wp-screen.php');
        require_once(ABSPATH . 'wp-admin/includes/template.php');
        $myListTable = new My_Example_List_Table();
    }

    echo '</pre><div class="wrap"><h2>Мой тест таблицы</h2>';
    $myListTable->prepare_items();

?>
<form method="post">
    <input type="hidden" name="page" value="ttest_list_table">
<?php

    $myListTable->search_box('поиск', 'search_id');
    $myListTable->display();

    echo '</form></div>';
}
17 дек. 2015 г. 23:24:02
Комментарии

Таким образом, вы загружаете (очень рано) 4 файла при каждом фронтенд-запросе, даже для страниц, которые не используют функцию my_render_list_page(). Почему бы не подключить файл и не создать экземпляр класса внутри самой функции my_render_list_page()? Это сделает код проще, читаемее и избавит от глобальных переменных...

gmazzap gmazzap
19 дек. 2015 г. 02:30:33

Хорошее замечание, @gmazzap

jgraup jgraup
24 авг. 2016 г. 23:03:34

@jgraup Спасибо за решение. Оно работает. Однако у меня появляется уведомление об ошибке: Notice: Undefined index: hook_suffix in \wp-admin\includes\class-wp-screen.php on line 213

samjco-com samjco-com
15 сент. 2019 г. 05:54:06