Typically when trying to convert or send data in a CSV format, it requires logic to build up the CSV, and then file pointers and additional PHP functions to actually convert your data to a CSV file format using functions such as fopen, fputcsv, and fclose.

This function will handle all of that, and convert an array of key/value arrays to a CSV formatted string. The associative array's keys specify the CSV columns the associated value falls under.

Numerous options exist to customize the format of the CSV file including using custom line endings, delimiters, enclosures, escape characters, whether or not the title row should be included, and finally if the output should be returned as a string or sent to the browser prompting the client to download and save the CSV.

All you need to do is build up each row of data for the CSV, and then send it to the arrayToCsv function.

In order to have custom line ending support, it requires you to also include the fputcsvEol function.

 * Convert an Array to CSV format
 * This function depends on a custom PHP function called fputcsvEol which extends PHP's fputcsv to allow for custom
 * line endings. Either include this function, or change fputcsvEol to fputcsv.
 * @see https://www.ozzu.com/snippets/608143/extended-php-fputcsv-with-custom-line-endings
 * This function will convert an array of key/value pair arrays that represent the row/column. It requires an array of
 * key/value arrays like the following:
 * $data = [
 *     [
 *         'colHead1' => 'row1Col1Value',
 *         'colHead2' => 'row1Col2Value',
 *         'colHead3' => 'row1Col3Value',
 *         'colHead4' => 'row1Col4Value',
 *     ],
 *     [
 *         'colHead1' => 'row2Col1Value',
 *         'colHead2' => 'row2Col2Value',
 *         'colHead3' => 'row2Col3Value',
 *         'colHead4' => 'row2Col4Value',
 *     ],
 *     [
 *         'colHead1' => 'row3Col1Value',
 *         'colHead2' => 'row3Col2Value',
 *         'colHead3' => 'row3Col3Value',
 *         'colHead4' => 'row3Col4Value',
 *     ],
 * ];
 * The expected CSV output would be:
 * colHead1, colHead2, colHead3, colHead4
 * row1Col1Value, row1Col2Value, row1Col3Value, row1Col4Value
 * row2Col1Value, row2Col2Value, row2Col3Value, row2Col4Value
 * row3Col1Value, row3Col2Value, row3Col3Value, row3Col4Value
 * @param array $data The array of key/value arrays that is being converted to a CSV
 * @param null|string $filename If null simply returns csv result. If a string, the file prompted for browser to save as
 * @param bool $titleRow True if first row in CSV should be titles (the array keys)
 * @param string $delimiter How to separate the values in the CSV, default uses commas
 * @param string $enclosure By default uses double quotes around data
 * @param string $escapeChar By default uses '\\'
 * @param string $eol The line endings utilized in the CSV. By default uses "\n"
 * @return bool|string Return false on failure, string if no filename specified, or exits if sends to browser
function arrayToCsv($data, $filename = null, $titleRow = true, $delimiter = ',', $enclosure = '"', $escapeChar = '\\', $eol = "\n")
    if (! is_array($data) && ! is_array($data[0])) {
        return false;

    $fp = tmpfile();

    if($titleRow) {
        fputcsvEol($fp, array_keys($data[0]), $delimiter, $enclosure, $escapeChar, $eol);

    foreach ($data as $subArray) {
        fputcsvEol($fp, $subArray, $delimiter, $enclosure, $escapeChar, $eol);

    $contents = stream_get_contents($fp, -1, 0);

    // If filename is set, send headers that will force the browser to download the file
    if ($filename) {
        header("Content-type: application/octet-stream");
        header("Content-Disposition: attachment; filename=$filename");
        header("Pragma: no-cache");
        header("Expires: 0");

        echo $contents;

    return $contents;

This code snippet was published on It was last edited on

Contributing Authors



  • Votes
  • Oldest
  • Latest