WordPress create admin reports using WP_List_Table

In this post I’m going to discuss how to use WP_List_Table to create reports/tables/lists that are similar in style to the standard WordPress reports for Posts, Pages etc.

To achieve this I’ll use the WP_List_Table core WordPress class, this contains the functionality to create said tables/reports.

This example will look at the links table and display the data from it. This code used here is adapted from an example plugin on WordPress.org by Matt Van Andel

Important information to mention about creating admin reports using WP_List_Table

Its important to mention that this class is marked private by WordPress and they could change it in the future, without warning  (I’d be surprised if they did, given alot of peoples code relies on this class, but you never know). To be extra safe you can make a copy of the class in your own code and include this.

Explanation of the Code

The complete source code for the how to create admin reports using WP_List_Table plugin, is below. I’ve stripped out alot of the original comments. Please download the original plugin from WordPress.org to see the original version with comments (my version is adapted to run a SQL query and output the results as a report, the original doesn’t use SQL instead a pre-populated array is used for simplicity).

I’ll discuss in brief what the plugin does, first include the links report (this is hidden by default now in wp), I’m going to use this functionality to load wp_links with data that I can show on my report (for testing purposes):

add_filter('pre_option_link_manager_enabled', '__return_true');

Next the WP_List_Table class is included, this isn’t available by default to plugins. Then a class is created that inherits from WP_List_Table (this class will override the necessary methods of its parent class to give us the functionality we require).

Following this we have the column_default and get_columns methods. Column default tells class what to print in the report for each column. get_columns tells the class what our columns are.

The next part is the prepare_items method, this is where the magic happens. We query the database and setup the required information for our pagination and so on. After this the final 2 functions deal with putting a menu item on the left of the admin dashboard and the actual report display and we’re all good.

I hope you’ve found this interesting. Creating admin reports using WP_List_Table, is very useful for creating reports that are in the style of wordpress admin.

The complete code for how to create admin reports using WP_List_Table


add_filter('pre_option_link_manager_enabled', '__return_true');
  Plugin Name: WP Admin Custom List Table

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

class TT_Example_List_Table extends WP_List_Table {

    function __construct() {
        global $status, $page;

        //Set parent defaults
            'singular' => 'Nice Link', //singular name of the listed records
            'plural' => 'Nice Links', //plural name of the listed records
            'ajax' => false        //does this table support ajax?

    function column_default($item, $column_name) {
        switch ($column_name) {
            case 'link_id':
            case 'link_name':
                return "value of $column_name: " . $item->$column_name;
                return "col name = $column_name , " . print_r($item, true); //Show the whole array for troubleshooting purposes

    function get_columns() {
        return $columns = array(
            'link_id' => __('ID'),
            'link_name' => __('Name'),
            'link_url' => __('Url'),
            'link_description' => __('Description'),
            'link_visible' => __('Visible')
    function prepare_items() {
        global $wpdb; //This is used only if making any database queries

           /* -- Preparing your query -- */
        $query = "SELECT * FROM $wpdb->links";

        /* -- Ordering parameters -- */
        //Parameters that are going to be used to order the result
        $orderby = !empty($_GET["orderby"]) ? mysql_real_escape_string($_GET["orderby"]) : 'ASC';
        $order = !empty($_GET["order"]) ? mysql_real_escape_string($_GET["order"]) : '';
        if (!empty($orderby) & !empty($order)) {
            $query.=' ORDER BY ' . $orderby . ' ' . $order;

        $totalitems = $wpdb->query($query);

         * First, lets decide how many records per page to show
        $perpage = 5;

        //Which page is this?
        $paged = !empty($_GET["paged"]) ? mysql_real_escape_string($_GET["paged"]) : '';
        //Page Number
        if (empty($paged) || !is_numeric($paged) || $paged <= 0) {
            $paged = 1;

        //How many pages do we have in total?
        $totalpages = ceil($totalitems / $perpage);
        //adjust the query to take pagination into account
        if (!empty($paged) && !empty($perpage)) {
            $offset = ($paged - 1) * $perpage;
            $query.=' LIMIT ' . (int) $offset . ',' . (int) $perpage;

        /* -- Register the pagination -- */
            "total_items" => $totalitems,
            "total_pages" => $totalpages,
            "per_page" => $perpage,

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

        $this->_column_headers = array($columns, $hidden, $sortable);

        $this->items = $wpdb->get_results($query);


function tt_add_menu_items() {
    add_menu_page('Example Plugin List Table', 'List Table Example', 'activate_plugins', 'tt_list_test', 'tt_render_list_page');

add_action('admin_menu', 'tt_add_menu_items');

function tt_render_list_page() {

    //Create an instance of our package class...
    $testListTable = new TT_Example_List_Table();
    //Fetch, prepare, sort, and filter our data...
    <div class="wrap">

        <div id="icon-users" class="icon32"><br/></div>
        <h2>List Table Test</h2>       

        <!-- Forms are NOT created automatically, so you need to wrap the table in one to use features like bulk actions -->
        <form id="movies-filter" method="get">
            <!-- For plugins, we also need to ensure that the form posts back to our current page -->
            <input type="hidden" name="page" value="<?php echo $_REQUEST['page'] ?>" />
            <!-- Now we can render the completed list table -->
    <?php $testListTable->display() ?>

    <?php }


Leave a Comment