DevPinoy.org
A Filipino Developers Community
   
I hate PHP gotchas

I like PHP, but some of its gotchas are really getting on my nerves. I wonder if any of you have encountered this particular issue that's been causing my hair to fall off lately.

One system I did for a client was generating badly-formed reports in CSV format. The mysterious thing was that it worked OK (even with their test data) on my home system using PHP 5.1.6.  I had to create my own fputcsv() function (for writing a row of data into a file in CSV format) because the version used by the client in production (together with some other web app system which I will dare not touch) is PHP 5.0.4.  Even when I forced my home machine to make use of the home-made fputcsv() function, my home machine seemed to generate OK reports.

What I noticed with the generated CSV files (from my client's server machine) was that some characters near the end of the comma-separated row were not present. As a result when the file is loaded into Excel, multiple records (rows) are concatenated into a single row, causing it to exceed Excel's 256-column limit and throw up some error message.

Until now I could not find the reason why it's behaving that way on PHP 5.0.4. A snippet of my home-made fputcsv function is shown below:

$lineToWrite = '';
foreach ($inputArr as $columnValue) {
$columnValue = str_replace('"', '""', $columnValue);
if ($lineToWrite != '') $lineToWrite .= ',';
$lineToWrite .= '"'.$columnValue.'"';
}
fputs($fp, $lineToWrite, strlen($lineToWrite));
fputs($fp, "\n");

I changed it to:

$lineStarted = false;
foreach ($inputArr as $columnValue) {
$columnValue = str_replace('"', '""', $columnValue);
if ($lineStarted) {
fputs($fp, ',');
} else {
$lineStarted = true;
}
fputs($fp, '"');
fputs($fp, $columnValue, strlen($columnValue));
fputs($fp, '"');
}
fputs($fp, "\n");

And it worked. For some reason it didn't want to display the whole string ($lineToWrite). At first I thought that the fputs or fwrite function have some sort of maximum string length limit, but there's no mention at all of that in the PHP documentation. Since the string being written to the CSV file had some of its latter characters chopped off, the opening double quote (") delimiting a column value is not being properly matched with a closing quote. The result is that the next column (first column of the succeeding row) is mistakenly taken to be part of the last column of the previous row. To solve the problem, I no longer concatenate the entire comma-separated row into a single string, and I write out the comma (column delimiters) and the opening and closing double quotes per column value in separate fputs() calls. Ugh. I really hate PHP gotchas.


Posted 04-26-2007 4:11 PM by cruizer
Filed under:
Copyright DevPinoy 2005-2008