• Hey, I’m trying to use WP_List_Table to show data from a table in the database and I’ve managed to get everything working to a point but my table is not showing any data.

    When I look at the HTML markup, it just shows the correct amount of tr elements in a row, but the elements themselves are empty and without any data.

    Is there an obvious thing that I’ve done wrong here?

Viewing 3 replies - 1 through 3 (of 3 total)
  • Moderator bcworkz

    (@bcworkz)

    One thing obvious to me is you’ve posted no code to show what you’ve attempted to do, so it is very difficult to say what you’ve done wrong other than you have not correctly handled the data output ??

    Thread Starter danieltj

    (@danieltj)

    Sorry, I was in a bit of a rush and forgot about the code! I’ve been seeing what other plugins have done to achieve this and they seem to be on the same lines as myself from what I can tell. This is my code for the WP_List_Table class.

    <?php
    
    if ( ! class_exists( 'WP_List_Table' ) ) {
    	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
    }
    
    class Log_Table extends WP_List_Table {
    
    	public function __construct() {
    
    		parent::__construct([
    			'singular' => __('Log', 'asdf'),
    			'plural' => __('Logs', 'asdf'),
    			'ajax' => false
    		]);
    
    	}
    
    	function get_columns() {
    
    		$columns = [
    			'cb'        => '<input type="checkbox" />',
    			'log_id'    => __('ID', 'asdf'),
    			'action'    => __('Action', 'asdf'),
    			'user_id'   => __('By User', 'asdf'),
    			'notes'     => __('Notes', 'asdf'),
    			'timestamp' => __('Date', 'asdf')
    		];
    
    		return $columns;
    
    	}
    
    	function column_default($item, $column_name) {
    
    		return $item[$column_name];
    
    	}
    
    	function column_log_id($item) {
    
    		$delete_nonce = wp_create_nonce('dtjwpb_delete_log');
    
    		$title = '<strong>' . $item['log_id'] . '</strong>';
    
    		$actions = [
    			'delete' => sprintf( '<a href="?page=%s&action=%s&log=%s&_wpnonce=%s">Delete</a>', esc_attr( $_REQUEST['page'] ), 'delete', absint( $item['log_id'] ), $delete_nonce )
    		];
    
    		return $title . $this->row_actions( $actions );
    
    	}
    
    	function column_action($item) {
    		return $item['action'];
    	}
    
    	function column_user_id($item) {
    		return $item['user_id'];
    	}
    
    	function column_notes($item) {
    		return $item['notes'];
    	}
    
    	function column_timestamp($item) {
    		return $item['timestamp'];
    	}
    
    	function get_bulk_actions() {
    
    		$actions = array(
    			'delete' => __('Delete', 'asdf')
    		);
    
    		return $actions;
    	
    	}
    
    	function get_sortable_columns() {
    
    		$sortable_columns = array(
    			'timestamp'  => array('timestamp', true)
    		);
    
    		return $sortable_columns;
    	
    	}
    
    	function no_items() {
    	
    		_e('No logs are available.', 'asdf');
    	
    	}
    
    	function prepare_items() {
    
    		global $wpdb;
    
    		$this->_column_headers = $this->get_column_info();
    		$this->process_bulk_action();
    
    		$per_page     = $this->get_items_per_page('logs_per_page', 20);
    		$current_page = $this->get_pagenum();
    		$total_items  = self::record_count();
    
    		$this->set_pagination_args( [
    			'total_items' => $total_items,
    			'per_page'    => $per_page,
    			'total_pages' => ceil($total_items / $per_page)
    		] );
    
    		$query = "SELECT * FROM " . $wpdb->prefix . TABLE;
    
    		if ( ! empty( $_REQUEST['orderby'] ) ) {
    			$query .= ' ORDER BY ' . esc_sql( $_REQUEST['orderby'] );
    			$query .= ! empty( $_REQUEST['order'] ) ? ' ' . esc_sql( $_REQUEST['order'] ) : ' ASC';
    		}
    
    		$query .= " LIMIT $per_page";
    		//$query .= ' OFFSET ' . ($page_number - 1) * $per_page;
    
    		$log_table_data = $wpdb->get_results($query);
    		$this->items = $log_table_data;
    		$log_table_count = $wpdb->get_var( "SELECT COUNT(*) FROM " . $wpdb->prefix . TABLE);
    		$this->total_items = $log_table_count;
    
    	}
    
    	static function delete_log( $id ) {
    
    		global $wpdb;
    
    		$wpdb->delete(
    			$wpdb->prefix . TABLE,
    			[
    				'log_id' => $id
    			]
    		);
    
    	}
    
    	function process_bulk_action() {
    
    		if ( 'delete' === $this->current_action() ) {
    
    			$nonce = esc_attr( $_REQUEST['_wpnonce'] );
    
    			if ( ! wp_verify_nonce($nonce, 'dtjwpb_delete_log') ) {
    				die('Error');
    			} else {
    				self::delete_log( absint( $_GET['log'] ) );
    				wp_redirect( esc_url_raw(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'] );
    
    			foreach ($delete_ids as $id) {
    				self::delete_log($id);
    			}
    
    			wp_redirect( esc_url_raw(add_query_arg()) );
    			exit;
    		
    		}
    	}
    
    }
    

    I then include that onto the actual template page and use the following to try and display the table. It shows up but just has empty tr tags between the bulk options above and below the table itself.

    <?php $log_table = new Log_Table(); ?>
    <?php $log_table->prepare_items(); ?>
    <?php $log_table->display(); ?>
    

    Anything obvious that I’m doing wrong? Thanks!

    • This reply was modified 7 years, 5 months ago by danieltj.
    • This reply was modified 7 years, 5 months ago by danieltj. Reason: Cleaned up the code
    Moderator bcworkz

    (@bcworkz)

    On the actual template page? So you are using WP List Table on the front end? I don’t think WP_List_Table is meant to be used like that, it’s supposed to be a back end thing. That’s not to say you cannot do so, but some tweaking may be required to basically trick WP_List_Table into thinking it is on a back end screen. I think mainly the tweaks are to avoid a bunch of warnings from being generated. The basic class functionality should be OK.

    The only other thing I see is in the column handling methods. I believe $item as passed to each method is a stdClass object, not an array. This would explain why the table cells are empty. If you reference a class property instead of an array element, content will be output.

    What you have basically looks OK. I’m not even sure what I’m seeing is really the case. Obviously something is not right. If you define WP_DEBUG as true in wp-config.php, (or just check your error logs) I’m pretty sure a number of warnings are being generated. If you work towards eliminating these you should be seeing proper results on output.

    Note that some servers may be configured to not log certain warnings and notices, so the lack of logged errors may not be a true indication unless you are sure all errors are being logged. WP_DEBUG ensures you see all errors on screen as they occur, so it’s a good option over relying on error logs. Just don’t leave WP_DEBUG active on an accessible site for a long time. It slightly increases security vulnerabilities.

Viewing 3 replies - 1 through 3 (of 3 total)
  • The topic ‘WP_List_Table not showing data’ is closed to new replies.