'Adding "export csv" option to wp list table bulk actions

I have a wp list table for custom db created with the help of this link. I added get_bulk_actions() and process_bulk_action() functions using this link and this link. I want to have 2 kinds of exports: all and selected. My problem is when I click "apply" for export-all or export-selected in bulk actions nothing happens. The plug-in's code is below:

<?php
/*
Plugin Name:  Status Table
*/

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

// Extending class
class Status_List_Table extends WP_List_Table
{
      private $status_data;

      private function get_status_data($search = "")
      {
        global $wpdb;

        if (!empty($search)) {
              return $wpdb->get_results(
                    "SELECT * FROM bpj5s_external_api_request_log WHERE request LIKE '%{$search}%' OR response LIKE '%{$search}%'",
                    ARRAY_A
              );
        }else{
              return $wpdb->get_results(
                "SELECT * FROM bpj5s_external_api_request_log",
                    ARRAY_A
              );
        }
      }

      // Define table columns
      function get_columns()
      {
            $columns = array(
                  'cb'            => '<input type="checkbox" />',
                  'id' => 'ID',
                  'status_code' => 'Status Code',
                  'status_message'    => 'Status Message',
                  'seqNumber' => 'Sequence Number'
            );
            return $columns;
      }

      function get_bulk_actions() {
            $actions = array(
              'export-all' => 'Export All',
              'export-selected' => 'Export Selected'
            );
            return $actions;
      }

      function process_bulk_action(){
            echo "<script>console.log('Testing');</script>";
            if ( "export-all" === $this->current_action() ){
                global $wpdb;
                
                header('Content-Type: text/csv');
                header('Content-Disposition: attachment; filename="export.csv"');
    
                // clean out other output buffers
                ob_end_clean();
    
                $fp = fopen('php://output', 'w');
    
                // CSV/Excel header label
                $header_row = array(
                    0 => 'id',
                    1 => 'created',
                    2 => 'name',
                    3 => 'request_headers',
                    4 => 'response_headers',
                    5 => 'request',
                    6 => 'response',
                    7 => 'request_time',
                    8 => 'status_message',
                    9 => 'status_code',
                );
    
                //write the header
                fputcsv($fp, $header_row);
    
                // retrieve any table data desired. Members is an example 
                $Table_Name   = 'bpj5s_external_api_request_log'; 
                $sql_query    = $wpdb->prepare("SELECT * FROM $Table_Name", 1) ;
                // $sql_query    = $wpdb->prepare("SELECT * FROM $Table_Name WHERE id IN($ids)", 1) ;
                $rows         = $wpdb->get_results($sql_query, ARRAY_A);
                if(!empty($rows)) 
                {
                    foreach($rows as $Record)
                    {  
                    $OutputRecord = array($Record['id'],
                                    $Record['created'],
                                    $Record['name'],
                                    $Record['request_headers'],
                                    $Record['response_headers'],
                                    $Record['request'],
                                    $Record['response'],
                                    $Record['request_time'],
                                    $Record['status_message'],  
                                    $Record['status_code']);
                    fputcsv($fp, $OutputRecord);       
                    }
                }
    
                fclose( $fp );
                exit;  
                // }              // Stop any more exporting to the file
            }
    
            if ( "export-selected" === $this->current_action() ){
                $ids = isset($_REQUEST['id']) ? $_REQUEST['id'] : array();
                if (is_array($ids)) $ids = implode(',', $ids);
               
                if (!empty($ids)) {
                    // Use headers so the data goes to a file and not displayed
                    global $wpdb;
                    
                    header('Content-Type: text/csv');
                    header('Content-Disposition: attachment; filename="export.csv"');
    
                    // clean out other output buffers
                    ob_end_clean();
    
                    $fp = fopen('php://output', 'w');
    
                    // CSV/Excel header label
                    $header_row = array(
                        0 => 'id',
                        1 => 'created',
                        2 => 'name',
                        3 => 'request_headers',
                        4 => 'response_headers',
                        5 => 'request',
                        6 => 'response',
                        7 => 'request_time',
                        8 => 'status_message',
                        9 => 'status_code',
                    );
    
                    //write the header
                    fputcsv($fp, $header_row);
    
                    // retrieve any table data desired. Members is an example 
                    $Table_Name   = 'bpj5s_external_api_request_log'; 
                    $sql_query    = $wpdb->prepare("SELECT * FROM $Table_Name WHERE id IN($ids)", 1) ;
                    $rows         = $wpdb->get_results($sql_query, ARRAY_A);
                    if(!empty($rows)) 
                    {
                        foreach($rows as $Record)
                        {  
                        $OutputRecord = array($Record['id'],
                                        $Record['created'],
                                        $Record['name'],
                                        $Record['request_headers'],
                                        $Record['response_headers'],
                                        $Record['request'],
                                        $Record['response'],
                                        $Record['request_time'],
                                        $Record['status_message'],  
                                        $Record['status_code']);
                        fputcsv($fp, $OutputRecord);       
                        }
                    }
    
                    fclose( $fp );
                    exit;  
                }            
            }
            
          }

      // Bind table with columns, data and all
      function prepare_items()
      {
            if (isset($_POST['page']) && isset($_POST['s'])) {
                  $this->status_data = $this->get_status_data($_POST['s']);
            } else {
                  $this->status_data = $this->get_status_data();
            }

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

            $this->process_bulk_action();

            /* pagination */
            $per_page = 20;
            $current_page = $this->get_pagenum();
            $total_items = count($this->status_data);

            $this->status_data = array_slice($this->status_data, (($current_page - 1) * $per_page), $per_page);

            $this->set_pagination_args(array(
                  'total_items' => $total_items, // total number of items
                  'per_page'    => $per_page // items to show on a page
            ));

            usort($this->status_data, array(&$this, 'usort_reorder'));

            $this->items = $this->status_data;
      }

      // bind data with column
      function column_default($item, $column_name)
      {
            switch ($column_name) {
                  case 'id':
                        return $item[$column_name];
                  case 'status_code':
                        return $item[$column_name];
                  case 'status_message':
                        return $item[$column_name];
                  case 'seqNumber':
                        return $item[$column_name];
                  default:
                        return print_r($item, true); //Show the whole array for troubleshooting purposes
            }
      }

      // To show checkbox with each row
      function column_cb($item)
      {
            return sprintf(
                  '<input type="checkbox" name="id[]" value="%s" />',
                  $item['id']
            );
      }

      // Add sorting to columns
      protected function get_sortable_columns()
      {
            $sortable_columns = array(
                //   'user_login'  => array('user_login', false),
                //   'display_name' => array('display_name', false),
                //   'user_email'   => array('user_email', true)
            );
            return $sortable_columns;
      }

      // Sorting function
      function usort_reorder($a, $b)
      {
            // If no sort, default to user_login
            $orderby = (!empty($_GET['orderby'])) ? $_GET['orderby'] : 'seqNumber';
            // If no order, default to asc
            $order = (!empty($_GET['order'])) ? $_GET['order'] : 'asc';
            // Determine sort order
            $result = strcmp($a[$orderby], $b[$orderby]);
            // Send final sort direction to usort
            return ($order === 'asc') ? $result : -$result;
      }
}

// Adding menu
function my_add_menu_items()
{
      add_menu_page('Status List Table', 'Status List Table', 'activate_plugins', 'status_list_table', 'status_list_init');
}
add_action('admin_menu', 'my_add_menu_items');

// Plugin menu callback function
function status_list_init()
{
      // Creating an instance
      $statusTable = new Status_List_Table();

      echo '<div class="wrap"><h2>Status List Table</h2>';
      // Prepare table
      $statusTable->prepare_items();
      ?>
            <form method="post">
                  <input type="hidden" name="page" value="my_list_test" />
                  <?php $statusTable->search_box('search', 'search_id'); ?>
            </form>
      <?php
      // Display table
      $statusTable->display();
      echo '</div>';
}


Solution 1:[1]

I fix the problem by inserting "$statusTable->display()" into "form" tag. Bulk actions must be kept inside form tags.

<form method="post">
   <input type="hidden" name="page" value="my_list_test" />
  <?php $statusTable->search_box('search', 'search_id'); ?>
  <?php $statusTable->display() ?>
</form>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 kadete