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   1320 Views

Avatar
zenmonkey

Community Member, 528 Posts

1 January 2011 at 9:45am

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

Forum Moderator, 474 Posts

1 January 2011 at 10:41am

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