WP_List_Table là class cho phép bạn tạo bất kỳ một bảng quản lý các thành phần nào trong admin. Như bạn thấy danh sách Posts, Pages hoặc Users trong WordPress đều kế thừa từ class WP_List_Table. Nếu trong giao diện hoặc plugin của bạn có các dữ liệu theo kiểu danh sách, và bạn muốn tạo trang quản lý danh sách này trong phần options thì bài viết này có thể sẽ giúp ích được cho bạn.
Tạo class kế thừa WP_List_Table
Để hiển thị bất kỳ danh sách nào thì bạn tạo 1 class kế thừa WP_List_Table.
<?php if ( ! class_exists( 'WP_List_Table' ) ) { require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' ); } class HPDL_API_Key_List_Table extends WP_List_Table { public $delete_posts; public $date_format; public $time_format; function __construct() { global $status, $page; $this->date_format = get_option( 'date_format' ); $this->time_format = get_option( 'time_format' ); parent::__construct( array( 'singular' => __( 'api_key', 'hocwp-pdl' ), 'plural' => __( 'api_keys', 'hocwp-pdl' ), 'ajax' => false ) ); add_action( 'admin_head', array( &$this, 'admin_header' ) ); } function admin_header() { global $plugin_page; if ( 'hocwp_pdl' != $plugin_page ) { return; } } function no_items() { _e( 'No API Key found, dude.', 'hocwp-pdl' ); } function column_default( $item, $column_name ) { switch ( $column_name ) { case 'id': return $item->ID; case 'date': $date = date( "$this->date_format $this->time_format", strtotime( $item->post_date ) ); return $date; case 'domain': case 'key': return get_post_meta( $item->ID, $column_name, true ); default: return print_r( $item, true ); } } function get_sortable_columns() { $sortable_columns = array( 'id' => array( 'id', false ), 'domain' => array( 'domain', false ), 'key' => array( 'key', false ), 'date' => array( 'date', false ) ); return $sortable_columns; } function get_columns() { $columns = array( 'cb' => '<input type="checkbox" />', 'id' => __( 'ID', 'hocwp-pdl' ), 'domain' => __( 'Domain', 'hocwp-pdl' ), 'key' => __( 'Key', 'hocwp-pdl' ), 'date' => __( 'Date', 'hocwp-pdl' ) ); return $columns; } function column_id( $item ) { global $plugin_page; $tab = 'api_keys'; $edit = admin_url( 'post.php?post=' . $item->ID . '&action=edit' ); $actions = array( 'edit' => sprintf( '<a href="%s">Edit</a>', $edit ), 'delete' => sprintf( '<a href="?page=%s&action=%s&api_key=%s&tab=%s">Delete</a>', $plugin_page, 'delete', $item->ID, $tab ), ); return sprintf( '%1$s %2$s', $item->ID, $this->row_actions( $actions ) ); } function get_bulk_actions() { $actions = array( 'delete' => __( 'Delete', 'hocwp-pdl' ) ); return $actions; } function column_cb( $item ) { return sprintf( '<input type="checkbox" name="api_keys[]" value="%s" />', $item->ID ); } function prepare_items() { $columns = $this->get_columns(); $hidden = array(); $sortable = $this->get_sortable_columns(); $this->_column_headers = array( $columns, $hidden, $sortable ); $per_page = get_option( 'posts_per_page' ); if ( ! is_numeric( $per_page ) ) { $per_page = 10; } $current_page = $this->get_pagenum(); $by = ( ! empty( $_GET['orderby'] ) ) ? $_GET['orderby'] : 'ID'; if ( 'id' == $by ) { $orderby = 'ID'; } elseif ( 'date' == $by ) { $orderby = 'date'; } else { $orderby = 'meta_value'; } $order = ( ! empty( $_GET['order'] ) ) ? $_GET['order'] : 'asc'; $args = array( 'post_type' => 'hpdl_api_key', 'posts_per_page' => $per_page, 'paged' => $current_page, 'orderby' => $orderby, 'order' => $order ); $s = isset( $_POST['s'] ) ? $_POST['s'] : ''; if ( ! empty( $s ) ) { $args['meta_query'] = array( 'relation' => 'or', array( 'key' => 'domain', 'value' => $s, 'compare' => 'like' ), array( 'key' => 'key', 'value' => $s, 'compare' => 'like' ) ); } switch ( $by ) { case 'key': case 'domain': $args['meta_key'] = $by; break; } $query = new WP_Query( $args ); if ( ! $query->have_posts() && is_numeric( $s ) ) { $args['post__in'] = array( $s ); unset( $args['meta_query'] ); $query = new WP_Query( $args ); } $total_items = $query->found_posts; $items = $query->posts; $this->set_pagination_args( array( 'total_items' => $total_items, 'per_page' => $per_page ) ); $this->found_data = $items; $this->items = $items; } public function process_bulk_action() { if ( isset( $_POST['_wpnonce'] ) && ! empty( $_POST['_wpnonce'] ) ) { $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING ); $action = 'bulk-' . $this->_args['plural']; if ( ! wp_verify_nonce( $nonce, $action ) ) { wp_die( 'Nope! Security check failed!', 'hocwp-pdl' ); } } $action = $this->current_action(); switch ( $action ) { case 'delete': $api_key = isset( $_GET['api_key'] ) ? $_GET['api_key'] : ''; $key = get_post( $api_key ); if ( $key instanceof WP_Post && 'hpdl_api_key' == $key->post_type ) { $deleted = wp_delete_post( $key->ID, true ); if ( false != $deleted ) { ?> <div class="notice notice-success is-dismissible"> <p> <strong><?php _e( 'Info:', 'hocwp-pdl' ); ?></strong> <?php printf( __( '%s API Key has been deleted.', 'hocwp-pdl' ), 1 ); ?> </p> </div> <?php } } else { $api_keys = isset( $_POST['api_keys'] ) ? $_POST['api_keys'] : ''; if ( is_array( $api_keys ) ) { $count = 0; foreach ( $api_keys as $api_key ) { $key = get_post( $api_key ); if ( $key instanceof WP_Post && 'hpdl_api_key' == $key->post_type ) { $deleted = wp_delete_post( $key->ID, true ); if ( false != $deleted ) { $count ++; } } } ?> <div class="notice notice-success is-dismissible"> <p> <strong><?php _e( 'Info:', 'hocwp-pdl' ); ?></strong> <?php printf( __( '%s API Key deleted.', 'hocwp-pdl' ), $count ); ?> </p> </div> <?php } } break; } } }
Đoạn code bên trên mình tạo 1 custom post type là hpdl_api_key
. Sau đó, mình muốn hiển thị danh sách các API Key trên trang options thay vì quản lý như post bình thường. Đoạn code tạo custom post type mình có như sau:
$labels = array( 'name' => _x( 'API Keys', 'post type general name', 'hocwp-pdl' ), 'singular_name' => _x( 'API Key', 'post type singular name', 'hocwp-pdl' ), 'menu_name' => _x( 'API Keys', 'admin menu', 'hocwp-pdl' ), 'name_admin_bar' => _x( 'API Key', 'add new on admin bar', 'hocwp-pdl' ), 'add_new' => _x( 'Add New', 'api key', 'hocwp-pdl' ), 'add_new_item' => __( 'Add New API Key', 'hocwp-pdl' ), 'new_item' => __( 'New API Key', 'hocwp-pdl' ), 'edit_item' => __( 'Edit API Key', 'hocwp-pdl' ), 'view_item' => __( 'View API Key', 'hocwp-pdl' ), 'all_items' => __( 'All API Keys', 'hocwp-pdl' ), 'search_items' => __( 'Search API Keys', 'hocwp-pdl' ), 'parent_item_colon' => __( 'Parent API Keys:', 'hocwp-pdl' ), 'not_found' => __( 'No API Key found.', 'hocwp-pdl' ), 'not_found_in_trash' => __( 'No API Key found in Trash.', 'hocwp-pdl' ) ); $args = array( 'labels' => $labels, 'show_in_nav_menus' => false, 'show_in_menu' => true, 'show_in_admin_bar' => false, 'show_ui' => true, 'capabilities' => array( 'edit_post' => 'manage_options', 'read_post' => 'manage_options', 'delete_post' => 'manage_options', 'edit_posts' => 'manage_options', 'edit_others_posts' => 'manage_options', 'publish_posts' => 'manage_options', 'read_private_posts' => 'manage_options', 'create_posts' => 'manage_options', 'delete_posts' => 'manage_options' ), 'supports' => array( 'revisions' ), 'rewrite' => false, 'exclude_from_search' => true, 'publicly_queryable' => false ); register_post_type( 'hpdl_api_key', $args );
Chú ý là bạn phải để đoạn code trên vào trong action init
của WordPress nhé.
Hiển thị danh sách trong list table
Để hiển thị danh sách này thì mình tạo 1 action admin_notices
như bên dưới:
function hocwp_pdl_admin_notices_action() { global $pagenow, $plugin_page; if ( 'hocwp_pdl' == $plugin_page ) { global $hocwp_pdl; $hocwp_pdl->list_api_keys_table->process_bulk_action(); } } add_action( 'admin_notices', 'hocwp_pdl_admin_notices_action' );
Bạn thay hocwp_pdl
thành slug trang option mà bạn đang viết. Cuối cùng là trong hàm callback hiển thị HTML của trang option bạn để như sau:
<div style="padding-top: 20px;"> <a href="<?php echo admin_url( 'edit.php?post_type=hpdl_api_key' ); ?>" class="page-title-action button-primary" style="display: none"><?php _e( 'View Full Lists', 'hocwp-pdl' ); ?></a> <a href="<?php echo admin_url( 'post-new.php?post_type=hpdl_api_key' ); ?>" class="page-title-action"><?php _e( 'Add New', 'hocwp-pdl' ); ?></a> <?php global $hocwp_pdl, $plugin_page; $hocwp_pdl->list_api_keys_table->prepare_items(); ?> <form method="post"> <input type="hidden" name="page" value="<?php echo $plugin_page; ?>"> <?php $hocwp_pdl->list_api_keys_table->search_box( __( 'Search Key', 'hocwp-pdl' ), 'search_id' ); $hocwp_pdl->list_api_keys_table->display(); ?> </form> </div>
Như vậy là bạn đã có thể hiển thị danh sách bất kỳ theo kiểu quản lý danh sách bài viết hoặc tài khoản. Bài viết chỉ mang tính chất tham khảo, các bạn không nên sao chép mà chỉ nên áp dụng có chọn lọc. Chúc bạn thành công.
Bài biết rất hữu ích, cảm ơn bạn nhé
Cảm ơn Cường vì đã chia sẻ,
mình đã tìm cách giải quyết vấn đề này từ lâu mà chưa được giờ thì đã làm được rồi.
Cảm ơn Cường đã chia sẻ nhé.
Cảm ơn bạn đã ghé thăm, chúc trang web mau phát triển nhé.
đang cần cảm ơn nhé
Cho mình hỏi. Mình đã tạo 1 bảng bằng WP_List_Table trong backend. Có thể show cái bảng đó ra ngoài frontend không?
Mình chưa thử nhưng chắc là được. Có điều bạn phải load các hàm liên quan cũng như css để hiển thị giống admin.
Mình không phải dân code. Nên rất mong chờ thử nghiệm và hướng dẫn từ bạn. Cảm ơn vì những chia sẻ của bạn.
Hì, mình sử dụng cách này và custompost để tạo ra các danh mục truyện trên web mình như truyện tranh riêng, truyện chữ riêng, các truyện tính phí riêng, do các truyện đều tự động cập nhật nên phải phân ra như vậy để đỡ mắc công nhiều chỗ,
Chào bạn. Bạn có thể hướng dẫn mình hiển thị 1 bảng đã tạo bằng WP_List_Table trong backend ra ngoài frontend không?
bạn muốn hiển thị danh sách đơn thuần hay theo chuyên mục – bài mới
Danh sách mình lấy thông tin từ file json. Mình có tạo một submenu để hiển thị trong backend. Và giờ mình muốn hiển thị trang này ra ngoài frontend.