Статьи

Использование WP_List_Table для создания таблиц администратора WordPress

В панели управления WordPress таблицы, отображающие сообщения, страницы и пользовательские данные, все создаются внутри WordPress с использованием PHP-класса WP_List_Table .

Ниже приведено несколько скриншотов постов и пользовательских страниц администратора:

Image-2 - пост WordPress и страницы администратора пользователя

Изображение 1 - пост WordPress и страницы администратора пользователя

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

Хотя у вас может возникнуть соблазн скопировать дизайн таблиц HTML и CSS, просмотрев исходный код WordPress, этого не следует WP_List_Table поскольку класс WP_List_Table поможет вам.

Мое знакомство с WP_List_Table проистекает из моего опыта создания плагина ProfilePress . Я на самом деле использовал его для отображения списка созданных форм учетных записей пользователей в виде таблицы.

image-3 - ProfilePress каталог

Вы, вероятно, использовали плагины, которые используют WP_List_Table, например, популярный плагин Contact Form 7 использует класс для отображения списка созданных контактных форм.

Знакомство с WP_List_Table

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

Рисунок 4 - Пример базы данных клиентов

Плагин состоит из двух классов: дочерний класс WP_List_Table и класс настроек плагина.

Расширение WP_List_Table

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

Во-первых, мы включаем класс в плагин.

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

Затем мы создаем дочерний класс, который расширяет WP_List_Table . Дочерний класс будет называться Customers_List так как мы имеем дело с базой данных клиентов.

 class Customers_List extends WP_List_Table { /** Class constructor */ public function __construct() { parent::__construct( [ 'singular' => __( 'Customer', 'sp' ), //singular name of the listed records 'plural' => __( 'Customers', 'sp' ), //plural name of the listed records 'ajax' => false //should this table support ajax? ] ); } 

Давайте создадим несколько вспомогательных методов, которые будет использовать дочерний класс.

Приведенный ниже метод get_customers() запрашивает базу данных клиентов и возвращает данные в формате массива.

 /** * Retrieve customer's data from the database * * @param int $per_page * @param int $page_number * * @return mixed */ public static function get_customers( $per_page = 5, $page_number = 1 ) { global $wpdb; $sql = "SELECT * FROM {$wpdb->prefix}customers"; if ( ! empty( $_REQUEST['orderby'] ) ) { $sql .= ' ORDER BY ' . esc_sql( $_REQUEST['orderby'] ); $sql .= ! empty( $_REQUEST['order'] ) ? ' ' . esc_sql( $_REQUEST['order'] ) : ' ASC'; } $sql .= " LIMIT $per_page"; $sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page; $result = $wpdb->get_results( $sql, 'ARRAY_A' ); return $result; } 

Если вы создали приложение PHP / MySQL, включающее разбиение на страницы, синтаксис SQL OFFSET и LIMIT должен быть вам знаком.

$per_page и $page_number определяют ограничение SQL и номер текущей страницы.

Чтобы узнать больше о разбивке на страницы набора данных, см. Эти руководства .

Метод delete_customer() заботится об удалении данной записи из базы данных.

 /** * Delete a customer record. * * @param int $id customer ID */ public static function delete_customer( $id ) { global $wpdb; $wpdb->delete( "{$wpdb->prefix}customers", [ 'ID' => $id ], [ '%d' ] ); } 

record_count() просто возвращает количество клиентов в базе данных.

 /** * Returns the count of records in the database. * * @return null|string */ public static function record_count() { global $wpdb; $sql = "SELECT COUNT(*) FROM {$wpdb->prefix}customers"; return $wpdb->get_var( $sql ); } 

Мы закончили создание наших вспомогательных методов, все последующие методы нацелены на переопределение их соответствующих родительских методов.

Например, в WP_List_Table есть метод no_items() который возвращает No items found если данные не найдены.

Чтобы включить пользовательское сообщение, мы должны создать тот же метод в нашем дочернем классе, но с другим возвращаемым сообщением.

 /** Text displayed when no customer data is available */ public function no_items() { _e( 'No customers avaliable.', 'sp' ); } 

Метод column_name отображает имя столбца таблицы. Ссылка для удаления добавляется под именем клиента, передавая массив, содержащий ключ и значение row_action метод row_action .

 /** * Method for name column * * @param array $item an array of DB data * * @return string */ function column_name( $item ) { // create a nonce $delete_nonce = wp_create_nonce( 'sp_delete_customer' ); $title = '<strong>' . $item['name'] . '</strong>'; $actions = [ 'delete' => sprintf( '<a href="?page=%s&action=%s&customer=%s&_wpnonce=%s">Delete</a>', esc_attr( $_REQUEST['page'] ), 'delete', absint( $item['ID'] ), $delete_nonce ) ]; return $title . $this->row_actions( $actions ); } 

Поскольку выходные данные столбца адреса и города не будут изменены, метод column_default , функция которого заключается в визуализации столбца, если для этого столбца не существует специального метода, будет обрабатывать их вывод.

 /** * Render a column when no column specific method exists. * * @param array $item * @param string $column_name * * @return mixed */ public function column_default( $item, $column_name ) { switch ( $column_name ) { case 'address': case 'city': return $item[ $column_name ]; default: return print_r( $item, true ); //Show the whole array for troubleshooting purposes } } 

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

 /** * Render the bulk edit checkbox * * @param array $item * * @return string */ function column_cb( $item ) { return sprintf( '<input type="checkbox" name="bulk-delete[]" value="%s" />', $item['ID'] ); } 

Метод get_columns() возвращает массив столбцов, которые будут использоваться в вашей таблице.

 /** * Associative array of columns * * @return array */ function get_columns() { $columns = [ 'cb' => '<input type="checkbox" />', 'name' => __( 'Name', 'sp' ), 'address' => __( 'Address', 'sp' ), 'city' => __( 'City', 'sp' ) ]; return $columns; } 

Метод get_sortable_columns() определяет столбцы для сортировки. Таким образом, WordPress добавит ссылку на заголовок столбца, который при нажатии изменяет порядок представления данных.

 /** * Columns to make sortable. * * @return array */ public function get_sortable_columns() { $sortable_columns = array( 'name' => array( 'name', true ), 'city' => array( 'city', false ) ); return $sortable_columns; } 

get_bulk_actions() должна возвращать ассоциативный массив, содержащий все массовые действия, доступные для таблицы.

 /** * Returns an associative array containing the bulk action * * @return array */ public function get_bulk_actions() { $actions = [ 'bulk-delete' => 'Delete' ]; return $actions; } 

В методе prepare_items выполняется запрос и фильтрация данных, обработка сортировки, разбиение на страницы и любые другие манипуляции с данными, необходимые перед визуализацией.

Примечание: метод должен включать в себя вызов свойств родительского класса items и сохранять в нем массив данных базы данных.

 /** * Handles data query and filter, sorting, and pagination. */ public function prepare_items() { $this->_column_headers = $this->get_column_info(); /** Process bulk action */ $this->process_bulk_action(); $per_page = $this->get_items_per_page( 'customers_per_page', 5 ); $current_page = $this->get_pagenum(); $total_items = self::record_count(); $this->set_pagination_args( [ 'total_items' => $total_items, //WE have to calculate the total number of items 'per_page' => $per_page //WE have to determine how many items to show on a page ] ); $this->items = self::get_customers( $per_page, $current_page ); } 

Обратите внимание на вызов process_bulk_action() ? Этот метод заботится об удалении записи клиентов либо при нажатии на ссылку удаления, либо при проверке группы записей и выборе опции удаления в массовом действии.

 public function process_bulk_action() { //Detect when a bulk action is being triggered... if ( 'delete' === $this->current_action() ) { // In our file that handles the request, verify the nonce. $nonce = esc_attr( $_REQUEST['_wpnonce'] ); if ( ! wp_verify_nonce( $nonce, 'sp_delete_customer' ) ) { die( 'Go get a life script kiddies' ); } else { self::delete_customer( absint( $_GET['customer'] ) ); wp_redirect( esc_url( add_query_arg() ) ); exit; } } // If the delete bulk action is triggered if ( ( isset( $_POST['action'] ) && $_POST['action'] == 'bulk-delete' ) || ( isset( $_POST['action2'] ) && $_POST['action2'] == 'bulk-delete' ) ) { $delete_ids = esc_sql( $_POST['bulk-delete'] ); // loop over the array of record IDs and delete them foreach ( $delete_ids as $id ) { self::delete_customer( $id ); } wp_redirect( esc_url( add_query_arg() ) ); exit; } } 

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

Создание страницы настроек

Мы создаем класс для страницы настроек, заполненной методом и свойствами конструктора.

 class SP_Plugin { // class instance static $instance; // customer WP_List_Table object public $customers_obj; // class constructor public function __construct() { add_filter( 'set-screen-option', [ __CLASS__, 'set_screen' ], 10, 3 ); add_action( 'admin_menu', [ $this, 'plugin_menu' ] ); } 

Ниже приведены методы обратного вызова для фильтра set-screen-option и admin_menu действий admin_menu .

 public static function set_screen( $status, $option, $value ) { return $value; } public function plugin_menu() { $hook = add_menu_page( 'Sitepoint WP_List_Table Example', 'SP WP_List_Table', 'manage_options', 'wp_list_table_class', [ $this, 'plugin_settings_page' ] ); add_action( "load-$hook", [ $this, 'screen_option' ] ); } 

plugin_menu() которые создают страницу настроек, включают метод callback screen_option() для создания опции экрана для установки количества данных по умолчанию для отображения в таблице.

image-5 - опция экрана

 /** * Screen options */ public function screen_option() { $option = 'per_page'; $args = [ 'label' => 'Customers', 'default' => 5, 'option' => 'customers_per_page' ]; add_screen_option( $option, $args ); $this->customers_obj = new Customers_List(); } 

Обратите внимание: мы создали экземпляр дочернего класса Customers_List и сохранили объект в свойстве Customers_List определенном ранее в объявлении класса.

Ниже приведен plugin_settings_page обратного вызова plugin_settings_page который отображает содержимое страницы настроек.

 /** * Plugin settings page */ public function plugin_settings_page() { ?> <div class="wrap"> <h2>WP_List_Table Class Example</h2> <div id="poststuff"> <div id="post-body" class="metabox-holder columns-2"> <div id="post-body-content"> <div class="meta-box-sortables ui-sortable"> <form method="post"> <?php $this->customers_obj->prepare_items(); $this->customers_obj->display(); ?> </form> </div> </div> </div> <br class="clear"> </div> </div> <?php } 

Из приведенного выше кода таблица покупателя отображается с помощью первого вызова prepare_items() для подготовки данных, а затем display() для отображения содержимого таблицы.

Чтобы убедиться, что существует только один экземпляр объекта, вот метод singleton.

 /** Singleton instance */ public static function get_instance() { if ( ! isset( self::$instance ) ) { self::$instance = new self(); } return self::$instance; } 

Наконец, мы вызываем метод singleton, когда все плагины были загружены WordPress.

 add_action( 'plugins_loaded', function () { SP_Plugin::get_instance(); } ); 

Когда плагин установлен и активирован, вы увидите отображение данных о клиентах в пользовательском интерфейсе таблицы WordPress, как показано на рисунке ниже.

изображение 6 - Данные клиентов в пользовательском интерфейсе таблицы WordPress

Резюме

В этом руководстве мы рассмотрели, как отображать пользовательские данные, извлеченные из базы данных, в табличном формате с использованием мощного WP_List_Table PHP WP_List_Table .

Исходный код плагина доступен на GitHub . Загрузите, установите его на свой сайт на WordPress и изучите код.

Если у вас есть какие-либо вопросы или предложения, сообщите нам об этом в комментариях.