title: Why does my custom WP_List_Table not return any results?
body: <p>I have built a plugin to display results a custom table I have built in my Wordpress DB, following the tutorial found on <a href="https://www.smashingmagazine.com/2011/11/native-admin-tables-wordpress/" rel="nofollow noreferrer">Smashing Magazine</a> I have built the following code:</p>
  
  <pre><code>&lt;?php
  /*
  Plugin Name: Post Tracker
  Version: 0.1
  */
  add_action('admin_menu', 'yt_plugin_setup_menu');
  
  function yt_plugin_setup_menu(){
      add_menu_page( 'Post Tracker Plugin', 'Post Tracker', 'manage_options', 'tracker', 'tracker_init' );
  }
  
  //Our class extends the WP_List_Table class, so we need to make sure that it's there
  if(!class_exists('WP_List_Table')){
     require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
  }
  
  class Link_List_Table extends WP_List_Table {
  
     /**
      * Constructor, we override the parent to pass our own arguments
      * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
      */
      function __construct() {
         parent::__construct( array(
        'singular'=&gt; 'yt_tracker_link', //Singular label
        'plural' =&gt; 'yt_tracker_links', //plural label, also this well be one of the table css class
        'ajax'   =&gt; false //We won't support Ajax for this table
        ) );
      }
  
      /**
       * Add extra markup in the toolbars before or after the list
       * @param string $which, helps you decide if you add the markup after (bottom) or before (top) the list
       */
      function extra_tablenav( $which ) {
         if ( $which == "top" ){
            //The code that goes before the table is here
            echo"Hello, I'm before the table";
         }
         if ( $which == "bottom" ){
            //The code that goes after the table is there
            echo"Hi, I'm after the table";
         }
      }
  
      /**
       * Define the columns that are going to be used in the table
       * @return array $columns, the array of columns to use with the table
       */
      function get_columns() {
         return $columns= array(
            'col_id'=&gt;__('ID'),
            'col_post_id'=&gt;__('Post'),
            'col_last_checked'=&gt;__('Last Checked'),
            'col_last_reviewed'=&gt;__('Last Reviewed')
         );
      }
  
      /**
       * Decide which columns to activate the sorting functionality on
       * @return array $sortable, the array of columns that can be sorted by the user
       */
      function get_sortable_columns() {
         return $sortable = array(
            'col_last_checked'=&gt;'last_checked',
            'col_last_reviewed'=&gt;'last_checked'
         );
      }
  
      /**
       * Prepare the table with different parameters, pagination, columns and table elements
       */
      function prepare_items() {
         global $wpdb, $_wp_column_headers;
         $screen = get_current_screen();
  
         /* -- Preparing your query -- */
              $query = "SELECT * FROM yt_tracker";
  
         /* -- 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) &amp; !empty($order)){ $query.=' ORDER BY '.$orderby.' '.$order; }
  
         /* -- Pagination parameters -- */
              //Number of elements in your table?
              $totalitems = $wpdb-&gt;query($query); //return the total number of affected rows
              //How many to display per page?
              $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&lt;=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) &amp;&amp; !empty($perpage)){ $offset=($paged-1)*$perpage; $query.=' LIMIT '.(int)$offset.','.(int)$perpage; }
              /* -- Register the pagination -- */ 
              $this-&gt;set_pagination_args( array(
               "total_items" =&gt; $totalitems,
               "total_pages" =&gt; $totalpages,
               "per_page" =&gt; $perpage,
            ) );
            //The pagination links are automatically built according to those parameters
  
         /* -- Register the Columns -- */
            $columns = $this-&gt;get_columns();
            $_wp_column_headers[$screen-&gt;id]=$columns;
  
         /* -- Fetch the items -- */
            $this-&gt;items = $wpdb-&gt;get_results($query);
      }
  
      /**
       * Display the rows of records in the table
       * @return string, echo the markup of the rows
       */
      function display_rows() {
  
         //Get the records registered in the prepare_items method
         $records = $this-&gt;items;
  
         //Get the columns registered in the get_columns and get_sortable_columns methods
         list( $columns, $hidden ) = $this-&gt;get_column_info();
  
         //Loop for each record
         if(!empty($records)){foreach($records as $rec){
  
            //Open the line
              echo '&lt; tr id="record_'.$rec-&gt;id.'"&gt;';
            foreach ( $columns as $column_name =&gt; $column_display_name ) {
  
               //Style attributes for each col
               $class = "class='$column_name column-$column_name'";
               $style = "";
               if ( in_array( $column_name, $hidden ) ) $style = ' style="display:none;"';
               $attributes = $class . $style;
  
               //edit link
               $editlink  = '/wp-admin/link.php?action=edit&amp;link_id='.(int)$rec-&gt;link_id;
  
               //Display the cell
               switch ( $column_name ) {
                  case "col_id":  echo '&lt; td '.$attributes.'&gt;'.$rec-&gt;id.'&lt; /td&gt;';   break;
                  case "col_post_id": echo '&lt; td '.$attributes.'&gt;'.$rec-&gt;post_id.'7&lt; /td&gt;'; break;
                  case "col_last_checked": echo '&lt; td '.$attributes.'&gt;'.$rec-&gt;last_checked.'&lt; /td&gt;'; break;
                  case "col_last_reviewed": echo '&lt; td '.$attributes.'&gt;'.$rec-&gt;last_reviewed.'&lt; /td&gt;'; break;
               }
            }
  
            //Close the line
            echo'&lt; /tr&gt;';
         }}
      }
  
  }
  
  
  function tracker_init() {
  
      //Prepare Table of elements
      $wp_list_table = new Link_List_Table();
      $wp_list_table-&gt;prepare_items();
  
      //Table of elements
      $wp_list_table-&gt;display();
  
  }
  
  ?&gt;
  </code></pre>
  
  <p>This is what my table schema looks like:
  <a href="https://i.stack.imgur.com/E0amG.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/E0amG.png" alt="enter image description here"></a></p>
  
  <p>My actual plugin page only returns the following:
  <a href="https://i.stack.imgur.com/GRkBp.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/GRkBp.png" alt="enter image description here"></a></p>
  
  <p>I believe it something to do with the column setup but I'm not sure what's wrong.</p>