Working with CSV files sucks. You have to handle different line endings and entries can be wrapped in double quotess which could have a comma inside of it preventing you from just using explode(). Thankfully, PHP provides two functions for working with CSV files that are super helpful.

fgetcsv

The first is fgetcsv which reads from a file handle and brings in single line broken into an array. If you've every worked with processing csv files before you know how awesome this is. As an example,

// this prevents problems with different line endings
// see http://www.thisprogrammingthing.com/2012/oddity-with-fgetcsv/
ini_set('auto_detect_line_endings', true);

$file = fopen('filePath', 'r') or die('Unable to open file!');

while(($row = fgetcsv($file)) !== false){
    // work with the lines here
}

fclose($file);

fputcsv

The other is fputcsv which writes to a file with the correct formatting for a CSV file:

$file = fopen('filePath', 'w') or die('Unable to open file!');

foreach($array as $row)
    fputcsv($file, $row);
}

fclose($file);

Output to the Browser

Occasionally, we want to create a CSV file for a user to download. We could save the file to disk and then redirect to the output but I would rather just output the results:

header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"output.csv\";" );
header("Content-Transfer-Encoding: binary"); 

// we're going to write directly to the output buffer
$file = fopen('php:://output', 'w') or die('Unable to open file!');

// output the header row
fputcsv($file, array_get_keys($array[0]));

foreach($array as $row)
    fputcsv($file, $row);
}

fclose($file);

Converting a CSV File Into an Associative Array

Using fgetcsv we can convert a CSV file into an associative array. I like this approach because then it doesn't mater what order the columns are in the CSV.

// this prevents problems with different line endings
// see http://www.thisprogrammingthing.com/2012/oddity-with-fgetcsv/
ini_set('auto_detect_line_endings', true);

$file = fopen('test.csv', 'r') or die('Unable to open file!');

$returnVal = array();
$header = null;

while(($row = fgetcsv($file)) !== false){
    if($header === null){
        $header = $row;
        continue;
    }

    $newRow = array();
    for($i = 0; $i<count($row); $i++){
        $newRow[$header[$i]] = $row[$i];
    }

    $returnVal[] = $newRow;
}

fclose($file);

// $returnVal now contains the contents of the CSV file
var_dump($returnVal);