Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

General Questions

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Outputting a CSV (not from DB table)


Reply

2 Posts   1300 Views

Avatar
zenmonkey

1 January 2011 at 9:45am Community Member, 528 Posts

I'm trying to create a csv report that calucualtes totals to be downloaded. I can write the file I'm just not sure how to get the button to push the file to the browser.

See bellow:

function downloadAirmilesReport(){
      $trainers = DataObject::get("Member", "MemberType = 'Trainer' OR MemberType = 'Supervisor' OR MemberType = 'Manager'");
      //CSV HeaderRow
      $report = array(array("Offer","Report Date", "Collector Number", "Amount"));
      
      
      //Open File
      $fp = fopen('AirmilesReport.csv', 'w');
      
      foreach ($trainers as $trainer) {
         $id = $trainer->ID;
         $memberType = $trainer->MemberType;
         
         switch ($memberType) {
            case "Trainer":
               $clients = DataObject::get("Client", "AirMilesApproved = 1 AND TrainerID = '$id'");
               $totalClients = $clients->count();
               $totalPoints = $totalClients * 20;
               break;
            case "Supervisor":
               $clients = DataObject::get("Client", "AirMilesApproved = 1 AND SupervisorID = '$id'");
               $totalClients = $clients->count();
               $totalPoints = $totalClients * 15;
               break;
            case "Manager":
               $clients = DataObject::get("Client", "AirMilesApproved = 1 AND ManagerID = '$id'");
               $totalClients = $clients->count();
               $totalPoints = $totalClients * 5;
               break;
         }
         
         if ($clients){
            //Add Row to CSV
            array_push($report,array("xxx", "01.01.01",$trainer->AirmilesID, $totalPoints)) ;
         }
         echo "<br>";
      }
      
      foreach ($report as $line){
         fputcsv($fp, $line);
      }
   
      
      fclose($fp);
      
      return $fp;
   }

Thanks

Avatar
simon_w

1 January 2011 at 10:41am Forum Moderator, 474 Posts

Since you'll need to read the contents of the file back, I'd use a temp file, rather than one with a constant name. So, instead of fopen():

$fp = tmpfile();

Then, instead of your current call to fclose():

$contents = '';
fseek($fp, 0);
while(!feof($fp)) $contents .= fread($fp, 8192);
fclose($fp);

return SS_HTTPRequest::send_file($contents, 'AirmilesReport.csv', 'text/csv');

What this does is gets PHP to create a temporary file, which you write your CSV data to, then it returns to the start of the file, reads the contents of it into $contents, closes the file (which also gets PHP to delete it, as it was created with tmpfile()), then gets SilverStripe to force the browser to download $contents as AirmilesReport.csv with mime-type text/csv