When I use fputcsv to write out a line to an open file handle, PHP will add an enclosing character to any column that it believes needs it, but will leave other columns with
A "quick and dirty" solution is to add ' ' at the end of all of your fields, if it's acceptable for you:
function addspace($v) {
return $v.' ';
}
fputcsv($handle, array_map('addspace', $fields));
PS: why it's working? see Volkerk answer ;)
Not happy with this solution but it is what I did and worked. The idea is to set an empty char as enclosure character on fputcsv and add some quotes on every element of your array.
function encodeFunc($value) {
return "\"$value\"";
}
fputcsv($handler, array_map(encodeFunc, $array), ',', chr(0));
Building on Martin's answer, if you want to avoid inserting any characters that don't stem from the source array (Chr(127)
, Chr(0)
, etc), you can replace the fputcsv() line with the following instead:
fputs($fp, implode(",", array_map("encodeFunc", $row))."\r\n");
Granted, fputs() is slower than fputcsv(), but it's a cleaner output. The complete code is thus:
/***
* @param $value array
* @return string array values enclosed in quotes every time.
*/
function encodeFunc($value) {
///remove any ESCAPED double quotes within string.
$value = str_replace('\\"','"',$value);
//then force escape these same double quotes And Any UNESCAPED Ones.
$value = str_replace('"','\"',$value);
//force wrap value in quotes and return
return '"'.$value.'"';
}
$fp = fopen("filename.csv", 'w');
foreach($table as $row){
fputs($fp, implode(",", array_map("encodeFunc", $row))."\r\n");
}
fclose($fp);
After a lot of scrafffing around and some somewhat tedious character checking, I have a version of the above referenced codes by Diego and Mahn that will correctly strip out encasings and replace with double quotes on all fields in fputcsv
. and then output the file to the browser to download.
I also had a secondary issue of not being able to be sure that double quotes were always / never escaped.
Specifically for when outputting directly to browser using the php://input stream as referenced by Diego. Chr(127)
is a space character so the CSV file has a few more spaces than otherwise but I believe this sidesteps the issue of chr(0)
NULL characters in UTF-8.
/***
* @param $value array
* @return string array values enclosed in quotes every time.
*/
function encodeFunc($value) {
///remove any ESCAPED double quotes within string.
$value = str_replace('\\"','"',$value);
//then force escape these same double quotes And Any UNESCAPED Ones.
$value = str_replace('"','\"',$value);
//force wrap value in quotes and return
return '"'.$value.'"';
}
$result = $array_Set_Of_DataBase_Results;
$fp = fopen('php://output', 'w');
if ($fp && $result) {
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="export-'.date("d-m-Y").'.csv"');
foreach($result as $row) {
fputcsv($fp, array_map("encodeFunc", $row), ',', chr(127));
}
unset($result,$row);
die;
}
I hope this is useful for some one.
No, fputcsv() only encloses the field under the following conditions
/* enclose a field that contains a delimiter, an enclosure character, or a newline */
if (FPUTCSV_FLD_CHK(delimiter) ||
FPUTCSV_FLD_CHK(enclosure) ||
FPUTCSV_FLD_CHK(escape_char) ||
FPUTCSV_FLD_CHK('\n') ||
FPUTCSV_FLD_CHK('\r') ||
FPUTCSV_FLD_CHK('\t') ||
FPUTCSV_FLD_CHK(' ')
)
There is no "always enclose" option.