After coming across invalid CSV export files from QuickPayPro I did a bit of searching and found that PHP surprisingly does not have a function to output CSV to the browser. PHP has a function for everything, I would have lost money on this bet. PHP 5 introduced fputcsv()
which outputs CSV data to a file, but there’s no support for simply outputting to the browser. Additionally fputcsv()
is weak and requires you to wrap your values with quotes yourself.
As this comes up from time to time and I’m sure not just for me, I put together a class that solves both of these problems. I may update it one day to add support for writing to files, but for now it’s just to send CSV data right to the browser. There’s an optional method to make the data an attachment with a custom name. Usage is a piece of cake, especially if your data is already organized in an array of associative arrays:
$data = array(array("one","two","three"), array(4,5,6));
$csv = new CSV_Writer($data);
$csv->headers('test');
$csv->output();
The client will be prompted to download a file called “test.csv” that has properly escaped CSV data. The full class is below.
CSV PHP Class
/**
* Simple class to properly output CSV data to clients. PHP 5 has a built
* in method to do the same for writing to files (fputcsv()), but many times
* going right to the client is beneficial.
*
* @author Jon Gales
*/
class CSV_Writer {
public $data = array();
public $deliminator;
/**
* Loads data and optionally a deliminator. Data is assumed to be an array
* of associative arrays.
*
* @param array $data
* @param string $deliminator
*/
function __construct($data, $deliminator = ",")
{
if (!is_array($data))
{
throw new Exception('CSV_Writer only accepts data as arrays');
}
$this->data = $data;
$this->deliminator = $deliminator;
}
private function wrap_with_quotes($data)
{
$data = preg_replace('/"(.+)"/', '""$1""', $data);
return sprintf('"%s"', $data);
}
/**
* Echos the escaped CSV file with chosen delimeter
*
* @return void
*/
public function output()
{
foreach ($this->data as $row)
{
$quoted_data = array_map(array('CSV_Writer', 'wrap_with_quotes'), $row);
echo sprintf("%s\n", implode($this->deliminator, $quoted_data));
}
}
/**
* Sets proper Content-Type header and attachment for the CSV outpu
*
* @param string $name
* @return void
*/
public function headers($name)
{
header('Content-Type: application/csv');
header("Content-disposition: attachment; filename={$name}.csv");
}
}
how if i want to do this one
$data = array(array(“one”,”A Quick brown fox jumps over the lazy dog”,”three”));
This works, the csv is outputted, but the 2nd one column keep its width so smaller, How to manage its width accordingly.
Thanks in advance
Thanks for this Jon, it’s great. The data I needed to export happened to already be an array of associative arrays, so implementing this was really simple.