List table not rendering when $this->items is filled

I did same error first time I implemented WP_List_Table.

The problem is that when you call WP_List_Table::display() WordPress in turn calls:

Last function is called for every row. If you look at its code (see source), it has:

if ( 'cb' == $column_name ) {
   // you don't have 'cb' column, code remove because not relevant
} elseif ( method_exists( $this, 'column_' . $column_name ) ) {
   // you don't have method named 'column_{$column_name}',
   // code remove because not relevant 
} else {
   // not relevant line
   echo $this->column_default( $item, $column_name );
}

So WordPress calls WP_List_Table::column_default() for every row, but… that method doesn’t exist.

Add to your class:

public function column_default($item, $column_name) {
    return $item[$column_name];
}

And your data will be correctly displayed.

When you don’t add data, error doesn’t show up because with no data WordPress never calls display_rows() and other methods after that.


Bonus Notes:

  1. In your prepare_items() method you use the variable $perpage but you define it as $per_page (notice the underscore), that cause a division-by-zero warning (and pagination doesn’t work)

  2. the code mysql_real_escape_string($_GET["orderby"]) is not safe, because for 'orderby' SQL clause mysql_real_escape_string() is not enough. (see recent Yoast SQL injection bug).

    Do something like:

    $orderby = 'id'; // default
    $by = strtolower(filter_input(INPUT_GET, 'orderby', FILTER_SANITIZE_STRING));
    if (in_array($by, array('title', 'description', 'user_id'), true) {
        $orderby = $by;
    }
    

    and do something similar to for 'order' clause as well: very probably it can only be either ASC or DESC: don’t allow anything else.

Leave a Comment