calebporzio's avatar

The best way to create and export a csv from a model?

In my current project, I need to be able to export an Eloquent Collection to a csv file and have it download.

I am aware there are packages available, but would rather not go that route.

The way I would love it to happen is:

$file = fopen('export.csv', 'w');

fwrite($file, 'csv formatted contents');

fclose($file);

Resource::download($file);

But I understand downloading the file through the Resource Facade won't work. Please give me any suggestions or input.

Thanks

0 likes
13 replies
mglinski's avatar

You do realize that you waste cycles and storage by saving it to a file first? Not to mention that the way you want to do it is either needlessly complex or will be buggy as all hell? Saving to a file first is a very good way to ensure that you will corrupt the file and someone will see data they are not supposed to.

Regardless, this is close enough to how you want do it:

// :: send download headers here ::
$data = $eloquentCollection->toArray();    
fputcsv($out, array_keys($data[1]));
$out = fopen('php://output', 'w');
foreach($data as $line)
{
    fputcsv($out, $line);
}
fclose($out);

This does not take into account edge cases or failure states. You will also need to investigate which headers you need to send to make this appear as a download to browsers.

4 likes
calebporzio's avatar

Thanks for the response. And also please recognize I am a beginner here just trying to learn like everyone else.

That looks good, I think what I was saying, are there any facades or other built-in laravel functionality that I could use for this purpose. I never intended to save the file before downloading.

That being said, I am fine with opening a few headers and spitting out a csv, just wondered if there was a cleaner way.

3 likes
calebporzio's avatar

Thanks @Felix, thats what I had set up before but had problems with the formatting of the export. For my purposes a robust package like that is overkill. My solution (using a packalyst package to format to csv):

public function export()
 {
  $entitiesArray = $this->entities->toArray();

  $formatter = Formatter::make($entitiesArray, Formatter::ARR);

  $csv = $formatter->toCsv();

  header('Content-Disposition: attachment; filename="export.csv"');
  header("Cache-control: private");
  header("Content-type: application/force-download");
  header("Content-transfer-encoding: binary\n");

  echo $csv;

  exit;
 }

Works like a charm. Of course any input or ways I could improve the code are welcomed.

MThomas's avatar

@calebporzio I can recommend @Ionut's solution. The package might be a little bigger than you might need but it will save you tons of work and it is easy to setup and use :)

calebporzio's avatar

Thanks Guys, but like I said, I came from using Maatwebsite. I was having issues with the formatting. If I abstract the export logic to a service, how is my solution not simpler? I don't need any of the other features of Maatwebsite's Excel package.

Is there something wrong with the code I posted?

thinkjay's avatar

@calebporzio hi i'm looking for a quick solution like you, i tried the code you posted but can't seem to get it to work, could you post your full code or a link on where you found that code?

thanks!

pmall's avatar

Is there something wrong with the code I posted?

No it is fine :)

Note that text files can also be formated with a blade view.

edgreenberg's avatar

I installed the csv package http://csv.thephpleague.com as recommended by @aardalich. I followed this: https://mattstauffer.co/blog/export-an-eloquent-collection-to-a-csv-with-league-csv

It worked on the first run, No errors or debugging. Simple and straightfoward.

I also need tab delimited output for my project. I found this: http://csv.thephpleague.com/properties/

The answer by @aardalich actually answers the question, rather than going off on a PHPExcel tangent, which is probably very valuable for those who need actual Excel output.

renanst's avatar

Hi,

I am not able to export my model. My model has 4 fields: id, name, fields and ETC. Where 'fields' and 'ETC' are json columns.

Please or to participate in this conversation.