CSV document output
Once your CSV document is loaded, you can print or enable downloading it using the methods below.
The output methods are affected by the output BOM sequence and/or the supplied PHP stream filters.
Printing the document
Returns the string representation of the CSV document.
public AbstractCsv::toString(void): string
public AbstractCsv::getContent(void): string
public AbstractCsv::__toString(void): string
Use the toString
method to return the full CSV content.
Example
use League\Csv\Reader;
$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');
echo $reader->toString();
Exceptions and Errors
If the CSV document is not seekable a Exception
or a RuntimeException
may be thrown when using getContent
. A Fatal Error
will be trigger when using the __toString
method.
Using the toString
method
use League\Csv\Writer;
$csv = Writer::createFromFileObject(new SplFileObject('php://output', 'w'));
$csv->insertOne(['foo', 'bar']);
echo $csv->toString();
//throws a RuntimeException because the SplFileObject is not seekable
Using the __toString
or getContent
methods
use League\Csv\Writer;
$csv = Writer::createFromFileObject(new SplFileObject('php://output', 'w'));
$csv->insertOne(['foo', 'bar']);
echo $csv;
echo $csv->getContent();
//throws a Fatal Error because no exception can be thrown by the __toString method
Downloading the document
To make your CSV document downloadable use the output
method to force the use of the output buffer on the CSV content.
public AbstractCsv::download(?string $filename = null): int
The method returns the number of characters read from the handle and passed through to the output.
The output method can take an optional argument $filename
. When present you can even remove more headers.
Default usage
use League\Csv\Reader;
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename="name-for-your-file.csv"');
$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');
$reader->download();
die;
Using the $filename argument
use League\Csv\Reader;
$reader = Reader::createFromPath('file.csv');
$reader->download('name-for-your-file.csv');
die;
Outputting the document into chunks
public AbstractCsv::chunk(int $length): Generator
The AbstractCsv::chunk
method takes a single $length
parameter specifying the number of bytes to read from the CSV document and returns a Generator
to ease outputting large CSV files.
use League\Csv\Reader;
header('Transfer-Encoding: chunked');
header('Content-Encoding: none');
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename="name-for-your-file.csv"');
$reader = Reader::createFromPath('/path/to/huge/file.csv', 'r');
foreach ($reader->chunk(1024) as $chunk) {
echo dechex(strlen($chunk))."\r\n$chunk\r\n";
}
echo "0\r\n\r\n";
Using a Response object (Symfony, Laravel, PSR-7 etc)
To avoid breaking the flow of your application, you should create a Response object when applicable in your framework. The actual implementation will differ per framework, but you should generally not output headers directly.
use League\Csv\Reader;
$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');
return new Response($reader->toString(), 200, [
'Content-Encoding' => 'none',
'Content-Type' => 'text/csv; charset=UTF-8',
'Content-Disposition' => 'attachment; filename="name-for-your-file.csv"',
'Content-Description' => 'File Transfer',
]);
In some cases you can also use a Streaming Response for larger files. The following example uses Symfony’s StreamedResponse object.
use League\Csv\Writer;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpFoundation\StreamedResponse;
//we generate the CSV using the Writer object
//$dbh is a PDO object
$stmt = $dbh->prepare("SELECT * FROM users");
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute();
$csv = Writer::createFromPath('php://temp', 'r+');
$csv->insertAll($stmt);
//we create a callable to output the CSV in chunks
//with Symfony StreamResponse you can flush the body content if necessary
//see Symfony documentation for more information
$flush_threshold = 1000; //the flush value should depend on your CSV size.
$content_callback = function () use ($csv, $flush_threshold) {
foreach ($csv->chunk(1024) as $offset => $chunk) {
echo $chunk;
if ($offset % $flush_threshold === 0) {
flush();
}
}
};
//we send the CSV using Symfony StreamedResponse
$response = new StreamedResponse();
$response->headers->set('Content-Encoding', 'none');
$response->headers->set('Content-Type', 'text/csv; charset=UTF-8');
$disposition = $response->headers->makeDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
'name-for-your-file.csv'
);
$response->headers->set('Content-Disposition', $disposition);
$response->headers->set('Content-Description', 'File Transfer');
$response->setCallback($content_callback);
$response->send();
Notes
The output methods can only be affected by:
No other method or property has an effect on them.