Working with CSV in PHP: complete guide
CSV (Comma-Separated Values) is one of the most popular formats for exchanging tabular data. PHP has both built-in functions for working with CSV and powerful third-party libraries. In this article, we will cover all the main ways to read, write, and process CSV files in PHP.
Built-in PHP functions for working with CSV
PHP provides several built-in functions that allow you to work with CSV files without installing additional libraries. The main ones are:
fgetcsv()— reading a line from a file and parsing it into an arrayfputcsv()— writing an array to a file in CSV formatstr_getcsv()— parsing a CSV string into an array
Reading a CSV file using fgetcsv
The fgetcsv() function reads one line from an open file and returns it as an array. Example of reading an entire file:
<?php$filename = 'data.csv';
if (($handle = fopen($filename, 'r')) !== false) { while (($data = fgetcsv($handle, 1000, ',')) !== false) { // $data — array with row data echo implode(' | ', $data) . ""; } fclose($handle);}?>Parameters of the fgetcsv() function:
handle— file handlelength— maximum line length (usually 0 or 1000)separator— field delimiter (default is comma)enclosure— field enclosure character (default is double quote)escape— escape character (default is backslash)
Writing data to a CSV file
For writing, the fputcsv() function is used. It takes an array and converts it into a CSV string:
<?php$data = [ ['Name', 'Age', 'City'], ['Ivan', 25, 'Moscow'], ['Maria', 30, 'Saint Petersburg'],];
$filename = 'output.csv';$handle = fopen($filename, 'w');
foreach ($data as $row) { fputcsv($handle, $row, ';', '"');}
fclose($handle);echo "File $filename successfully created!";?>In this example, we use a semicolon (;) as the delimiter, which is common in Russian-language CSV files.
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 line-by-line reading:
<?phpfunction processLargeCSV($filename) { $handle = fopen($filename, 'r'); // Skip the header if present $header = fgetcsv($handle); while (($row = fgetcsv($handle)) !== false) { // Process each row $processed = array_map('trim', $row); // Your processing logic goes here yield $processed; // Use a generator } fclose($handle);}
// Usageforeach (processLargeCSV('bigdata.csv') as $row) { // Work with each row individually echo "Processed row: " . implode(',', $row) . "";}?>Using generators (yield) allows you to process files of any size without memory overflow.
League\\Csv library for advanced work
For more complex tasks, it is recommended to use the league/csv library. It provides a convenient object-oriented interface and many additional features.
Installation via Composer:
composer require league/csvUsage example:
<?phprequire 'vendor/autoload.php';
use League\\Csv\\Reader;use League\\Csv\\Writer;
// Reading CSV$csv = Reader::createFromPath('data.csv', 'r');$csv->setHeaderOffset(0); // First row is the header
// Getting all records as ass