I know the theory behind this error however it is now driving me crazy again. I'm using Tonic in my application. With this library you redirect all traffic to your dispatch.php
script which then executes the appropriate Resource
and that Resource
return a Response
which is displayed (output) by dispatch.php
.
The output method of Response
look like this:
/**
* Output the response
*/
public function output()
{
foreach ($this->headers as $name => $value) {
header($name.': '.$value, true, $this->responseCode());
}
echo $this->body;
}
So AFAIK this tells us that you can't write anything to php output in your Resource
.
I now have a Resource
that dynamically generates a csv from an input csv and outputs it to the browser (it converts 1 column of the data to a different format).
$csv = fopen('php://output', 'w');
// sets header
$response->__set('contentDisposition:', 'attachment; filename="' . $fileName . '"');
while (($line = fgetcsv($filePointer, 0, ",", '"')) !== FALSE) {
// generate line
fputcsv($csv, $line);
}
fclose($filePointer);
return $response;
This works 100% fine. No issue with headers and the correct file is generated and offered for download. This is already confusing because we are writing to the output before headers are set? What does fputcsv actually do?
I have a second resource that does a similar thing but it outputs a custom file format (text file).
$output = fopen('php://output', 'w');
// sets header
$response->__set('contentDisposition:', 'attachment; filename="' . $fileName . '"');
while (($line = fgetcsv($filePointer, 0, ",", '"')) !== FALSE) {
// generate a record (multiple lines) not shown / snipped
fwrite($output, $record);
}
fclose($filePointer);
return $response;
The only difference is that it uses fwrite instead of fputcsv and bang
headers already sent by... // line number = fwrite()
This is very confusing! IMHO it should actually fail in both cases? Why does the first one work? how can I get the second one to work? (I can generate a huge string containing the file and put that into the responses body and it works. However files could be rather big (up to 50 mb) and hence want to avoid this.)