Working with CSV in PHP: Reading, Writing, and Data Processing
The CSV (Comma-Separated Values) format remains one of the most popular ways to exchange tabular data. PHP provides built-in functions for working with this format, making it an ideal choice for data import/export, integration with CRM, accounting systems, and report generation. In this article, we will cover the complete CSV workflow: from opening a file to handling complex cases with escaping and encodings.
Core PHP Functions for Working with CSV
PHP has two key functions: fgetcsv() for reading and fputcsv() for writing. They automatically handle delimiters, quotes, and escaping.
Reading a CSV File Line by Line
A basic example of reading a CSV using fgetcsv():
<?php$filename = 'data.csv';
if (($handle = fopen($filename, 'r')) !== false) { // Read headers (first line) $headers = fgetcsv($handle, 1000, ','); if ($headers !== false) { echo "Headers: " . implode(', ', $headers) . "<br>"; // Read data line by line while (($row = fgetcsv($handle, 1000, ',')) !== false) { echo "Row: " . implode(' | ', $row) . "<br>"; } } fclose($handle);}?>Parameters of fgetcsv():
handle— file handle (result of fopen)length— maximum line length (0 is recommended for automatic detection)separator— field delimiter (comma by default)enclosure— quote character (double quote by default)escape— escape character (backslash by default)
Writing Data to CSV
The fputcsv() function automatically formats a line with proper escaping:
<?php$data = [ ['ID', 'Name', 'Email', 'Registration Date'], [1, 'Ivan Petrov', 'ivan@example.com', '2024-01-15'], [2, 'Maria Sidorova', 'maria@example.com', '2024-02-20'], [3, 'Alexey "Professor" Ivanov', 'alex@example.com', '2024-03-10']];
$filename = 'users.csv';
if (($handle = fopen($filename, 'w')) !== false) { // Write BOM for correct Cyrillic display in Excel fwrite($handle, "\\xEF\\xBB\\xBF"); foreach ($data as $row) { fputcsv($handle, $row, ';'); // Use semicolon for Excel } fclose($handle); echo "File $filename successfully created!";}?>Processing Large CSV Files
When working with large files (hundreds of thousands of rows), it is important not to load the entire file into memory. Use streaming processing:
<?phpfunction processLargeCSV($filename, callable $callback) { $handle = fopen($filename, 'r'); if ($handle === false) { throw new Exception("Could not open file: $filename"); } $headers = fgetcsv($handle, 0, ','); if ($headers === false) { fclose($handle); throw new Exception("Empty file or error reading headers"); } $rowNumber = 1; while (($row = fgetcsv($handle, 0, ',')) !== false) { if (count($row) !== count($headers)) { // Skip rows with an incorrect number of fields continue; } // Combine headers with data $assocRow = array_combine($headers, $row); call_user_func($callback, $assocRow, $rowNumber); $rowNumber++; } fclose($handle);}
// Usage:processLargeCSV('bigdata.csv', function($row, $number) { echo "Row #$number: {$row['email']} - {$row['name']}<br>";});?>Working with Different Delimiters and Encodings
Often CSV fi