-
-
Save zuzuleinen/6db61b09465e9bc8a7ea to your computer and use it in GitHub Desktop.
<?php | |
use Symfony\Component\HttpFoundation\Response; | |
use Symfony\Bundle\FrameworkBundle\Controller\Controller; | |
class CsvController extends Controller | |
{ | |
/** | |
* Get a CSV file from an array | |
* | |
* @return \Symfony\Component\HttpFoundation\Response | |
*/ | |
public function csvAction() | |
{ | |
$list = array( | |
//these are the columns | |
array('Firstname', 'Lastname',), | |
//these are the rows | |
array('Andrei', 'Boar'), | |
array('John', 'Doe') | |
); | |
$fp = fopen('php://output', 'w'); | |
foreach ($list as $fields) { | |
fputcsv($fp, $fields); | |
} | |
$response = new Response(); | |
$response->headers->set('Content-Type', 'text/csv'); | |
//it's gonna output in a testing.csv file | |
$response->headers->set('Content-Disposition', 'attachment; filename="testing.csv"'); | |
return $response; | |
} | |
} |
But stream_get_contents($fp)
has to load the file in memory anyway?
Correct. But using php://temp
allow you to be smart, ie by using Symfony\Component\HttpFoundation\StreamedResponse
.
Agree
It's also worth to explain why one shouldn't write to php://output
in this case. That stream is the same one as the one used by echo
or print
statements. Obviously, you can also access it via ob_*
functions. The thing is - you've got no idea what's in it or who's going to write to it. I've had a case, where using it caused the Content-Type
of a response to randomly change between text/csv
and text/html
. In other words - weird things happened!
Switching to anything else, in my case to php://temp
(thanks Nyholm!), did the trick.
A bit late, but there is a class called CsvEncoder
. You can do something like this:
use Symfony\Component\Serializer\Encoder\CsvEncoder;
$csvEncoder = new CsvEncoder();
$data = [];
foreach ($people as $person) {
$data[] = [
'First Name' => $person->getFirstName(),
'Last Name' => $person->getLastName(),
];
}
$csv = $csvEncoder->encode($data, 'csv');
The array keys of each element in $data
are the headers. You can change the header order by doing something like this:
$headers = ['Last Name', 'First Name'];
$csv = $csvEncoder->encode($data, 'csv', [
'csv_headers' => $headers,
]);
Good questions.
Using your suggestion or
php://memory
will store the data in memory. If you have 100MB of CSV data then your PHP process will take at least 100MB of system memory.Using
php://temp
will automatically switch to use a temp file when the data is more than a few megabytes. There is a php.ini setting for this.See more in the manual: https://www.php.net/manual/en/wrappers.php.php