Search code examples
phpcsvcakephpcakephp-2.x

CakePHP: Export index view to CSV file


I have a mechanism in place to basically dump everything in a certain model to a CSV file.

public function export() {
    ini_set('max_execution_time', 600); //increase max_execution_time to 10 min if data set is very large
    //create a file
    $filename = "export_".date("Y.m.d").".csv";
    $csv_file = fopen('php://output', 'w');

    header('Content-type: application/csv');
    header('Content-Disposition: attachment; filename="'.$filename.'"');
    $results = $this->Requirement->find('all');
    // Column headings
    $header_row = array("Req #", "Identity", "Status", "Name", "Description", "Owner");
    fputcsv($csv_file,$header_row,',','"');

    // Loop to create CSV file rows
    foreach($results as $result)
    {
        // Array indexes correspond to the field names in your db table(s)
        $row = array(
            $result['Requirement']['req_number'],
            $result['Requirement']['or_identity'],
            $result['Requirement']['req_status'],
            $result['Requirement']['mission_id'],
            $result['Requirement']['description'],
            $result['Requirement']['req_owner']
        );

        fputcsv($csv_file,$row,',','"');
    }

    fclose($csv_file);

This works when we need to do bulk exports. What I need to do now is dump only my index view to a CSV file. This is the code for my index function in my controller:

public function index(){

    if(!empty($this->request->data['Requirement'])) {
        $this->Session->write('Requirement', $this->request->data['Requirement']);
    } else {
        $this->request->data['Requirement'] = $this->Session->read('Requirement');
    }
    $options = array('Requirement.mission_id' => $this->request->data['Requirement']['mission_id']);

    $this->Paginator->settings = $this->paginate;
    $this->set('requirements', $this->Paginator->paginate('Requirement', $options));
}

And these are the columns displayed in the view:

<?php foreach($requirements as $requirement): ?>
<tr>
    <td width="5%"><?php echo $requirement['Requirement']['req_number']; ?></td>
    <td width="15%"><?php echo $requirement['Requirement']['or_identity']; ?></td>
    <td width="10%"><?php echo $status = ($requirement['Requirement']['req_status'] == 0 ? 'Open' : 'Closed'); ?></td>
    <td width="15%"><?php echo $requirement['ReqIdentity']['req_name']; ?></td>
    <td width="50%"><?php echo $requirement['ReqIdentity']['req_description']; ?></td>
    <td width="10%"><?php echo $requirement['ReqIdentity']['req_owner']; ?></td>
</tr>
<?php endforeach; ?>

The index view is filtered on mission_id. How can I use my export function to just do an export of what my index function outputs?


Solution

  • A possible implementation:

    1. Move the code from your export() method to a csv() method, which creates a CSV file from the data passed inside a parameter, instead of retrieving it from the database:

      public function csv($results) {
          //code for your export() method, except for the line 
          //$results = $this->Requirement->find('all');
      }
      
    2. Rewrite your export() method to:

      public function export() {
          $results = $this->Requirement->find('all');
          $this->csv($results);
      }
      
    3. Add functionality to your index() action to detect an export condition:

      public function index(){
      
          if(!empty($this->request->data['Requirement'])) {
              $this->Session->write('Requirement', $this->request->data['Requirement']);
          } else {
              $this->request->data['Requirement'] = $this->Session->read('Requirement');
          }
          $options = array('Requirement.mission_id' => $this->request->data['Requirement']['mission_id']);
      
          $this->Paginator->settings = $this->paginate;
      
          if (!empty($this->request->params['named']['export'])) {
              $this->set('requirements', $this->Paginator->paginate('Requirement', $options));
          } else {
              $this->csv($this->Paginator->paginate('Requirement', $options));
          }
      }
      
    4. Add the following line to your index view:

      <?=$this->Html->link('Export',$this->here . "/export:true")?>